Merge "Implement setActivityLabelAndIcon()."
diff --git a/Android.mk b/Android.mk
index 33e64d0..e1c15470 100644
--- a/Android.mk
+++ b/Android.mk
@@ -85,6 +85,8 @@
core/java/android/app/IWallpaperManager.aidl \
core/java/android/app/IWallpaperManagerCallback.aidl \
core/java/android/app/admin/IDevicePolicyManager.aidl \
+ core/java/android/app/trust/ITrustManager.aidl \
+ core/java/android/app/trust/ITrustListener.aidl \
core/java/android/app/backup/IBackupManager.aidl \
core/java/android/app/backup/IFullBackupRestoreObserver.aidl \
core/java/android/app/backup/IRestoreObserver.aidl \
@@ -120,6 +122,7 @@
core/java/android/content/pm/IPackageDataObserver.aidl \
core/java/android/content/pm/IPackageDeleteObserver.aidl \
core/java/android/content/pm/IPackageInstallObserver.aidl \
+ core/java/android/content/pm/IPackageInstallObserver2.aidl \
core/java/android/content/pm/IPackageManager.aidl \
core/java/android/content/pm/IPackageMoveObserver.aidl \
core/java/android/content/pm/IPackageStatsObserver.aidl \
@@ -189,6 +192,8 @@
core/java/android/service/dreams/IDozeHardware.aidl \
core/java/android/service/dreams/IDreamManager.aidl \
core/java/android/service/dreams/IDreamService.aidl \
+ core/java/android/service/trust/ITrustAgentService.aidl \
+ core/java/android/service/trust/ITrustAgentServiceCallback.aidl \
core/java/android/service/wallpaper/IWallpaperConnection.aidl \
core/java/android/service/wallpaper/IWallpaperEngine.aidl \
core/java/android/service/wallpaper/IWallpaperService.aidl \
@@ -288,6 +293,7 @@
telephony/java/com/android/internal/telephony/ISms.aidl \
telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
wifi/java/android/net/wifi/IWifiManager.aidl \
+ wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl \
wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
packages/services/PacProcessor/com/android/net/IProxyService.aidl \
packages/services/Proxy/com/android/net/IProxyCallback.aidl \
diff --git a/api/current.txt b/api/current.txt
index d0a955f..df83c57 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28,6 +28,7 @@
field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
+ field public static final java.lang.String BIND_TRUST_AGENT_SERVICE = "android.permission.BIND_TRUST_AGENT_SERVICE";
field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
field public static final java.lang.String BIND_WALLPAPER = "android.permission.BIND_WALLPAPER";
field public static final java.lang.String BLUETOOTH = "android.permission.BLUETOOTH";
@@ -287,6 +288,7 @@
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 = 16843822; // 0x101042e
field public static final int animateFirstView = 16843477; // 0x10102d5
field public static final int animateLayoutChanges = 16843506; // 0x10102f2
field public static final int animateOnClick = 16843356; // 0x101025c
@@ -373,12 +375,19 @@
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 = 16843821; // 0x101042d
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 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 = 16843828; // 0x1010434
+ field public static final int colorButtonNormalColored = 16843830; // 0x1010436
+ field public static final int colorButtonPressed = 16843829; // 0x1010435
+ field public static final int colorButtonPressedColored = 16843831; // 0x1010437
+ field public static final int colorControlActivated = 16843827; // 0x1010433
+ field public static final int colorControlNormal = 16843826; // 0x1010432
field public static final int colorFocusedHighlight = 16843663; // 0x101038f
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
@@ -399,10 +408,10 @@
field public static final int content = 16843355; // 0x101025b
field public static final int contentAuthority = 16843408; // 0x1010290
field public static final int contentDescription = 16843379; // 0x1010273
- field public static final int controlX1 = 16843771; // 0x10103fb
- field public static final int controlX2 = 16843773; // 0x10103fd
- field public static final int controlY1 = 16843772; // 0x10103fc
- field public static final int controlY2 = 16843774; // 0x10103fe
+ field public static final int controlX1 = 16843799; // 0x1010417
+ field public static final int controlX2 = 16843801; // 0x1010419
+ field public static final int controlY1 = 16843800; // 0x1010418
+ field public static final int controlY2 = 16843802; // 0x101041a
field public static final int cropToPadding = 16843043; // 0x1010123
field public static final int cursorVisible = 16843090; // 0x1010152
field public static final int customNavigationLayout = 16843474; // 0x10102d2
@@ -465,6 +474,7 @@
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
@@ -505,13 +515,15 @@
field public static final int fastScrollOverlayPosition = 16843578; // 0x101033a
field public static final int fastScrollPreviewBackgroundLeft = 16843575; // 0x1010337
field public static final int fastScrollPreviewBackgroundRight = 16843576; // 0x1010338
- field public static final int fastScrollStyle = 16843766; // 0x10103f6
+ field public static final int fastScrollStyle = 16843794; // 0x1010412
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 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 fillViewport = 16843130; // 0x101017a
field public static final int filter = 16843035; // 0x101011b
field public static final int filterTouchesWhenObscured = 16843460; // 0x10102c4
@@ -531,7 +543,7 @@
field public static final int format12Hour = 16843722; // 0x10103ca
field public static final int format24Hour = 16843723; // 0x10103cb
field public static final int fragment = 16843491; // 0x10102e3
- field public static final int fragmentBreadCrumbsStyle = 16843765; // 0x10103f5
+ field public static final int fragmentBreadCrumbsStyle = 16843793; // 0x1010411
field public static final int fragmentCloseEnterAnimation = 16843495; // 0x10102e7
field public static final int fragmentCloseExitAnimation = 16843496; // 0x10102e8
field public static final int fragmentFadeEnterAnimation = 16843497; // 0x10102e9
@@ -660,6 +672,34 @@
field public static final int keyboardMode = 16843341; // 0x101024d
field public static final int keycode = 16842949; // 0x10100c5
field public static final int killAfterRestore = 16843420; // 0x101029c
+ field public static final int l_resource_pad1 = 16843792; // 0x1010410
+ field public static final int l_resource_pad10 = 16843783; // 0x1010407
+ field public static final int l_resource_pad11 = 16843782; // 0x1010406
+ field public static final int l_resource_pad12 = 16843781; // 0x1010405
+ field public static final int l_resource_pad13 = 16843780; // 0x1010404
+ field public static final int l_resource_pad14 = 16843779; // 0x1010403
+ field public static final int l_resource_pad15 = 16843778; // 0x1010402
+ field public static final int l_resource_pad16 = 16843777; // 0x1010401
+ field public static final int l_resource_pad17 = 16843776; // 0x1010400
+ field public static final int l_resource_pad18 = 16843775; // 0x10103ff
+ field public static final int l_resource_pad19 = 16843774; // 0x10103fe
+ field public static final int l_resource_pad2 = 16843791; // 0x101040f
+ field public static final int l_resource_pad20 = 16843773; // 0x10103fd
+ field public static final int l_resource_pad21 = 16843772; // 0x10103fc
+ field public static final int l_resource_pad22 = 16843771; // 0x10103fb
+ field public static final int l_resource_pad23 = 16843770; // 0x10103fa
+ field public static final int l_resource_pad24 = 16843769; // 0x10103f9
+ field public static final int l_resource_pad25 = 16843768; // 0x10103f8
+ field public static final int l_resource_pad26 = 16843767; // 0x10103f7
+ field public static final int l_resource_pad27 = 16843766; // 0x10103f6
+ field public static final int l_resource_pad28 = 16843765; // 0x10103f5
+ field public static final int l_resource_pad3 = 16843790; // 0x101040e
+ field public static final int l_resource_pad4 = 16843789; // 0x101040d
+ field public static final int l_resource_pad5 = 16843788; // 0x101040c
+ field public static final int l_resource_pad6 = 16843787; // 0x101040b
+ field public static final int l_resource_pad7 = 16843786; // 0x101040a
+ field public static final int l_resource_pad8 = 16843785; // 0x1010409
+ field public static final int l_resource_pad9 = 16843784; // 0x1010408
field public static final int label = 16842753; // 0x1010001
field public static final int labelFor = 16843718; // 0x10103c6
field public static final int labelTextSize = 16843317; // 0x1010235
@@ -715,6 +755,7 @@
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 = 16843823; // 0x101042f
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
field public static final int lines = 16843092; // 0x1010154
@@ -817,6 +858,7 @@
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 pathPattern = 16842796; // 0x101002c
field public static final int pathPrefix = 16842795; // 0x101002b
field public static final int permission = 16842758; // 0x1010006
@@ -826,7 +868,7 @@
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 = 16843778; // 0x1010402
+ field public static final int pinned = 16843825; // 0x1010431
field public static final int pivotX = 16843189; // 0x10101b5
field public static final int pivotY = 16843190; // 0x10101b6
field public static final int popupAnimationStyle = 16843465; // 0x10102c9
@@ -881,6 +923,7 @@
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
@@ -890,7 +933,7 @@
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
- field public static final int requiredForProfile = 16843777; // 0x1010401
+ field public static final int requiredForProfile = 16843824; // 0x1010430
field public static final int requiresFadingEdge = 16843685; // 0x10103a5
field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
field public static final int resizeMode = 16843619; // 0x1010363
@@ -954,6 +997,7 @@
field public static final int selectableItemBackground = 16843534; // 0x101030e
field public static final int selectedDateVerticalBar = 16843591; // 0x1010347
field public static final int selectedWeekBackgroundColor = 16843586; // 0x1010342
+ field public static final int sequence = 16843815; // 0x1010427
field public static final int settingsActivity = 16843301; // 0x1010225
field public static final int shadowColor = 16843105; // 0x1010161
field public static final int shadowDx = 16843106; // 0x1010162
@@ -961,7 +1005,7 @@
field public static final int shadowRadius = 16843108; // 0x1010164
field public static final int shape = 16843162; // 0x101019a
field public static final int shareInterpolator = 16843195; // 0x10101bb
- field public static final int sharedElementName = 16843775; // 0x10103ff
+ field public static final int sharedElementName = 16843803; // 0x101041b
field public static final int sharedUserId = 16842763; // 0x101000b
field public static final int sharedUserLabel = 16843361; // 0x1010261
field public static final int shouldDisableView = 16843246; // 0x10101ee
@@ -1025,6 +1069,10 @@
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 strokeOpacity = 16843812; // 0x1010424
+ field public static final int strokeWidth = 16843813; // 0x1010425
field public static final int subtitle = 16843473; // 0x10102d1
field public static final int subtitleTextStyle = 16843513; // 0x10102f9
field public static final int subtypeExtraValue = 16843674; // 0x101039a
@@ -1138,7 +1186,7 @@
field public static final int tileMode = 16843265; // 0x1010201
field public static final int timeZone = 16843724; // 0x10103cc
field public static final int tint = 16843041; // 0x1010121
- field public static final int tintMode = 16843770; // 0x10103fa
+ 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 titleTextStyle = 16843512; // 0x10102f8
@@ -1160,11 +1208,15 @@
field public static final int transformPivotX = 16843552; // 0x1010320
field public static final int transformPivotY = 16843553; // 0x1010321
field public static final int transition = 16843743; // 0x10103df
- field public static final int transitionGroup = 16843776; // 0x1010400
+ field public static final int transitionGroup = 16843804; // 0x101041c
field public static final int transitionOrdering = 16843744; // 0x10103e0
field public static final int translationX = 16843554; // 0x1010322
field public static final int translationY = 16843555; // 0x1010323
- field public static final int translationZ = 16843769; // 0x10103f9
+ 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 type = 16843169; // 0x10101a1
field public static final int typeface = 16842902; // 0x1010096
field public static final int uiOptions = 16843672; // 0x1010398
@@ -1189,6 +1241,8 @@
field public static final int verticalGap = 16843328; // 0x1010240
field public static final int verticalScrollbarPosition = 16843572; // 0x1010334
field public static final int verticalSpacing = 16843029; // 0x1010115
+ field public static final int viewportHeight = 16843807; // 0x101041f
+ field public static final int viewportWidth = 16843806; // 0x101041e
field public static final int visibility = 16842972; // 0x10100dc
field public static final int visible = 16843156; // 0x1010194
field public static final int vmSafeMode = 16843448; // 0x10102b8
@@ -1221,8 +1275,8 @@
field public static final int windowBackground = 16842836; // 0x1010054
field public static final int windowCloseOnTouchOutside = 16843611; // 0x101035b
field public static final int windowContentOverlay = 16842841; // 0x1010059
- field public static final int windowContentTransitionManager = 16843768; // 0x10103f8
- field public static final int windowContentTransitions = 16843767; // 0x10103f7
+ field public static final int windowContentTransitionManager = 16843796; // 0x1010414
+ field public static final int windowContentTransitions = 16843795; // 0x1010413
field public static final int windowDisablePreview = 16843298; // 0x1010222
field public static final int windowEnableSplitTouch = 16843543; // 0x1010317
field public static final int windowEnterAnimation = 16842932; // 0x10100b4
@@ -1295,10 +1349,20 @@
field public static final int app_icon_size = 17104896; // 0x1050000
field public static final int dialog_min_width_major = 17104899; // 0x1050003
field public static final int dialog_min_width_minor = 17104900; // 0x1050004
+ field public static final int l_resource_pad1 = 17104912; // 0x1050010
+ field public static final int l_resource_pad10 = 17104903; // 0x1050007
+ field public static final int l_resource_pad2 = 17104911; // 0x105000f
+ field public static final int l_resource_pad3 = 17104910; // 0x105000e
+ field public static final int l_resource_pad4 = 17104909; // 0x105000d
+ field public static final int l_resource_pad5 = 17104908; // 0x105000c
+ field public static final int l_resource_pad6 = 17104907; // 0x105000b
+ field public static final int l_resource_pad7 = 17104906; // 0x105000a
+ field public static final int l_resource_pad8 = 17104905; // 0x1050009
+ field public static final int l_resource_pad9 = 17104904; // 0x1050008
field public static final int notification_large_icon_height = 17104902; // 0x1050006
field public static final int notification_large_icon_width = 17104901; // 0x1050005
- field public static final int recents_thumbnail_height = 17104903; // 0x1050007
- field public static final int recents_thumbnail_width = 17104904; // 0x1050008
+ field public static final int recents_thumbnail_height = 17104913; // 0x1050011
+ field public static final int recents_thumbnail_width = 17104914; // 0x1050012
field public static final int thumbnail_height = 17104897; // 0x1050001
field public static final int thumbnail_width = 17104898; // 0x1050002
}
@@ -1512,7 +1576,27 @@
field public static final int inputArea = 16908318; // 0x102001e
field public static final int inputExtractEditText = 16908325; // 0x1020025
field public static final int keyboardView = 16908326; // 0x1020026
+ field public static final int l_resource_pad1 = 16908352; // 0x1020040
+ field public static final int l_resource_pad10 = 16908343; // 0x1020037
+ field public static final int l_resource_pad11 = 16908342; // 0x1020036
+ field public static final int l_resource_pad12 = 16908341; // 0x1020035
+ field public static final int l_resource_pad13 = 16908340; // 0x1020034
+ field public static final int l_resource_pad14 = 16908339; // 0x1020033
+ field public static final int l_resource_pad15 = 16908338; // 0x1020032
+ field public static final int l_resource_pad16 = 16908337; // 0x1020031
+ field public static final int l_resource_pad17 = 16908336; // 0x1020030
+ field public static final int l_resource_pad18 = 16908335; // 0x102002f
+ field public static final int l_resource_pad19 = 16908334; // 0x102002e
+ field public static final int l_resource_pad2 = 16908351; // 0x102003f
+ field public static final int l_resource_pad3 = 16908350; // 0x102003e
+ field public static final int l_resource_pad4 = 16908349; // 0x102003d
+ field public static final int l_resource_pad5 = 16908348; // 0x102003c
+ field public static final int l_resource_pad6 = 16908347; // 0x102003b
+ field public static final int l_resource_pad7 = 16908346; // 0x102003a
+ field public static final int l_resource_pad8 = 16908345; // 0x1020039
+ field public static final int l_resource_pad9 = 16908344; // 0x1020038
field public static final int list = 16908298; // 0x102000a
+ field public static final int mask = 16908354; // 0x1020042
field public static final int message = 16908299; // 0x102000b
field public static final int paste = 16908322; // 0x1020022
field public static final int primary = 16908300; // 0x102000c
@@ -1521,7 +1605,7 @@
field public static final int selectAll = 16908319; // 0x102001f
field public static final int selectTextMode = 16908333; // 0x102002d
field public static final int selectedIcon = 16908302; // 0x102000e
- field public static final int shared_element_name = 16908334; // 0x102002e
+ field public static final int shared_element_name = 16908353; // 0x1020041
field public static final int startSelectingText = 16908328; // 0x1020028
field public static final int stopSelectingText = 16908329; // 0x1020029
field public static final int summary = 16908304; // 0x1020010
@@ -1661,12 +1745,6 @@
field public static final int MediaButton_Play = 16973882; // 0x103003a
field public static final int MediaButton_Previous = 16973880; // 0x1030038
field public static final int MediaButton_Rew = 16973884; // 0x103003c
- field public static final int Quantum_ButtonBar = 16974498; // 0x10302a2
- field public static final int Quantum_ButtonBar_AlertDialog = 16974497; // 0x10302a1
- field public static final int Quantum_Light_ButtonBar = 16974501; // 0x10302a5
- field public static final int Quantum_Light_ButtonBar_AlertDialog = 16974500; // 0x10302a4
- field public static final int Quantum_Light_SegmentedButton = 16974502; // 0x10302a6
- field public static final int Quantum_SegmentedButton = 16974499; // 0x10302a3
field public static final int TextAppearance = 16973886; // 0x103003e
field public static final int TextAppearance_DeviceDefault = 16974253; // 0x10301ad
field public static final int TextAppearance_DeviceDefault_DialogWindowTitle = 16974264; // 0x10301b8
@@ -1682,13 +1760,13 @@
field public static final int TextAppearance_DeviceDefault_Widget = 16974265; // 0x10301b9
field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Menu = 16974286; // 0x10301ce
field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Subtitle = 16974279; // 0x10301c7
- field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Subtitle_Inverse = 16974283; // 0x10301cb
+ field public static final deprecated int TextAppearance_DeviceDefault_Widget_ActionBar_Subtitle_Inverse = 16974283; // 0x10301cb
field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Title = 16974278; // 0x10301c6
- field public static final int TextAppearance_DeviceDefault_Widget_ActionBar_Title_Inverse = 16974282; // 0x10301ca
+ field public static final deprecated int TextAppearance_DeviceDefault_Widget_ActionBar_Title_Inverse = 16974282; // 0x10301ca
field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Subtitle = 16974281; // 0x10301c9
- field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Subtitle_Inverse = 16974285; // 0x10301cd
+ field public static final deprecated int TextAppearance_DeviceDefault_Widget_ActionMode_Subtitle_Inverse = 16974285; // 0x10301cd
field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Title = 16974280; // 0x10301c8
- field public static final int TextAppearance_DeviceDefault_Widget_ActionMode_Title_Inverse = 16974284; // 0x10301cc
+ field public static final deprecated int TextAppearance_DeviceDefault_Widget_ActionMode_Title_Inverse = 16974284; // 0x10301cc
field public static final int TextAppearance_DeviceDefault_Widget_Button = 16974266; // 0x10301ba
field public static final int TextAppearance_DeviceDefault_Widget_DropDownHint = 16974271; // 0x10301bf
field public static final int TextAppearance_DeviceDefault_Widget_DropDownItem = 16974272; // 0x10301c0
@@ -1742,40 +1820,52 @@
field public static final int TextAppearance_Large_Inverse = 16973891; // 0x1030043
field public static final int TextAppearance_Medium = 16973892; // 0x1030044
field public static final int TextAppearance_Medium_Inverse = 16973893; // 0x1030045
- field public static final int TextAppearance_Quantum = 16974318; // 0x10301ee
- field public static final int TextAppearance_Quantum_DialogWindowTitle = 16974319; // 0x10301ef
- field public static final int TextAppearance_Quantum_Inverse = 16974320; // 0x10301f0
- field public static final int TextAppearance_Quantum_Large = 16974321; // 0x10301f1
- field public static final int TextAppearance_Quantum_Large_Inverse = 16974322; // 0x10301f2
- field public static final int TextAppearance_Quantum_Medium = 16974323; // 0x10301f3
- field public static final int TextAppearance_Quantum_Medium_Inverse = 16974324; // 0x10301f4
- field public static final int TextAppearance_Quantum_SearchResult_Subtitle = 16974325; // 0x10301f5
- field public static final int TextAppearance_Quantum_SearchResult_Title = 16974326; // 0x10301f6
- field public static final int TextAppearance_Quantum_Small = 16974327; // 0x10301f7
- field public static final int TextAppearance_Quantum_Small_Inverse = 16974328; // 0x10301f8
- field public static final int TextAppearance_Quantum_Widget = 16974330; // 0x10301fa
- field public static final int TextAppearance_Quantum_Widget_ActionBar_Menu = 16974331; // 0x10301fb
- field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle = 16974332; // 0x10301fc
- field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle_Inverse = 16974333; // 0x10301fd
- field public static final int TextAppearance_Quantum_Widget_ActionBar_Title = 16974334; // 0x10301fe
- field public static final int TextAppearance_Quantum_Widget_ActionBar_Title_Inverse = 16974335; // 0x10301ff
- field public static final int TextAppearance_Quantum_Widget_ActionMode_Subtitle = 16974336; // 0x1030200
- field public static final int TextAppearance_Quantum_Widget_ActionMode_Subtitle_Inverse = 16974337; // 0x1030201
- field public static final int TextAppearance_Quantum_Widget_ActionMode_Title = 16974338; // 0x1030202
- field public static final int TextAppearance_Quantum_Widget_ActionMode_Title_Inverse = 16974339; // 0x1030203
- field public static final int TextAppearance_Quantum_Widget_Button = 16974340; // 0x1030204
- field public static final int TextAppearance_Quantum_Widget_DropDownHint = 16974341; // 0x1030205
- field public static final int TextAppearance_Quantum_Widget_DropDownItem = 16974342; // 0x1030206
- field public static final int TextAppearance_Quantum_Widget_EditText = 16974343; // 0x1030207
- field public static final int TextAppearance_Quantum_Widget_IconMenu_Item = 16974344; // 0x1030208
- field public static final int TextAppearance_Quantum_Widget_PopupMenu = 16974345; // 0x1030209
- field public static final int TextAppearance_Quantum_Widget_PopupMenu_Large = 16974346; // 0x103020a
- field public static final int TextAppearance_Quantum_Widget_PopupMenu_Small = 16974347; // 0x103020b
- field public static final int TextAppearance_Quantum_Widget_TabWidget = 16974348; // 0x103020c
- field public static final int TextAppearance_Quantum_Widget_TextView = 16974349; // 0x103020d
- field public static final int TextAppearance_Quantum_Widget_TextView_PopupMenu = 16974350; // 0x103020e
- field public static final int TextAppearance_Quantum_Widget_TextView_SpinnerItem = 16974351; // 0x103020f
- field public static final int TextAppearance_Quantum_WindowTitle = 16974329; // 0x10301f9
+ field public static final int TextAppearance_Quantum = 16974346; // 0x103020a
+ field public static final int TextAppearance_Quantum_Body1 = 16974538; // 0x10302ca
+ field public static final int TextAppearance_Quantum_Body2 = 16974537; // 0x10302c9
+ field public static final int TextAppearance_Quantum_Button = 16974541; // 0x10302cd
+ field public static final int TextAppearance_Quantum_Caption = 16974539; // 0x10302cb
+ field public static final int TextAppearance_Quantum_DialogWindowTitle = 16974347; // 0x103020b
+ field public static final int TextAppearance_Quantum_Display1 = 16974533; // 0x10302c5
+ field public static final int TextAppearance_Quantum_Display2 = 16974532; // 0x10302c4
+ field public static final int TextAppearance_Quantum_Display3 = 16974531; // 0x10302c3
+ field public static final int TextAppearance_Quantum_Display4 = 16974530; // 0x10302c2
+ field public static final int TextAppearance_Quantum_Headline = 16974534; // 0x10302c6
+ field public static final int TextAppearance_Quantum_Inverse = 16974348; // 0x103020c
+ field public static final int TextAppearance_Quantum_Large = 16974349; // 0x103020d
+ field public static final int TextAppearance_Quantum_Large_Inverse = 16974350; // 0x103020e
+ field public static final int TextAppearance_Quantum_Medium = 16974351; // 0x103020f
+ field public static final int TextAppearance_Quantum_Medium_Inverse = 16974352; // 0x1030210
+ field public static final int TextAppearance_Quantum_Menu = 16974540; // 0x10302cc
+ field public static final int TextAppearance_Quantum_SearchResult_Subtitle = 16974353; // 0x1030211
+ field public static final int TextAppearance_Quantum_SearchResult_Title = 16974354; // 0x1030212
+ field public static final int TextAppearance_Quantum_Small = 16974355; // 0x1030213
+ field public static final int TextAppearance_Quantum_Small_Inverse = 16974356; // 0x1030214
+ field public static final int TextAppearance_Quantum_Subhead = 16974536; // 0x10302c8
+ field public static final int TextAppearance_Quantum_Title = 16974535; // 0x10302c7
+ field public static final int TextAppearance_Quantum_Widget = 16974358; // 0x1030216
+ field public static final int TextAppearance_Quantum_Widget_ActionBar_Menu = 16974359; // 0x1030217
+ field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle = 16974360; // 0x1030218
+ field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle_Inverse = 16974361; // 0x1030219
+ field public static final int TextAppearance_Quantum_Widget_ActionBar_Title = 16974362; // 0x103021a
+ field public static final int TextAppearance_Quantum_Widget_ActionBar_Title_Inverse = 16974363; // 0x103021b
+ field public static final int TextAppearance_Quantum_Widget_ActionMode_Subtitle = 16974364; // 0x103021c
+ field public static final int TextAppearance_Quantum_Widget_ActionMode_Subtitle_Inverse = 16974365; // 0x103021d
+ field public static final int TextAppearance_Quantum_Widget_ActionMode_Title = 16974366; // 0x103021e
+ field public static final int TextAppearance_Quantum_Widget_ActionMode_Title_Inverse = 16974367; // 0x103021f
+ field public static final int TextAppearance_Quantum_Widget_Button = 16974368; // 0x1030220
+ field public static final int TextAppearance_Quantum_Widget_DropDownHint = 16974369; // 0x1030221
+ field public static final int TextAppearance_Quantum_Widget_DropDownItem = 16974370; // 0x1030222
+ field public static final int TextAppearance_Quantum_Widget_EditText = 16974371; // 0x1030223
+ field public static final int TextAppearance_Quantum_Widget_IconMenu_Item = 16974372; // 0x1030224
+ field public static final int TextAppearance_Quantum_Widget_PopupMenu = 16974373; // 0x1030225
+ field public static final int TextAppearance_Quantum_Widget_PopupMenu_Large = 16974374; // 0x1030226
+ field public static final int TextAppearance_Quantum_Widget_PopupMenu_Small = 16974375; // 0x1030227
+ field public static final int TextAppearance_Quantum_Widget_TabWidget = 16974376; // 0x1030228
+ field public static final int TextAppearance_Quantum_Widget_TextView = 16974377; // 0x1030229
+ field public static final int TextAppearance_Quantum_Widget_TextView_PopupMenu = 16974378; // 0x103022a
+ field public static final int TextAppearance_Quantum_Widget_TextView_SpinnerItem = 16974379; // 0x103022b
+ field public static final int TextAppearance_Quantum_WindowTitle = 16974357; // 0x1030215
field public static final int TextAppearance_Small = 16973894; // 0x1030046
field public static final int TextAppearance_Small_Inverse = 16973895; // 0x1030047
field public static final int TextAppearance_StatusBar_EventContent = 16973927; // 0x1030067
@@ -1870,34 +1960,34 @@
field public static final int Theme_NoTitleBar_Fullscreen = 16973831; // 0x1030007
field public static final int Theme_NoTitleBar_OverlayActionModes = 16973930; // 0x103006a
field public static final int Theme_Panel = 16973913; // 0x1030059
- field public static final int Theme_Quantum = 16974352; // 0x1030210
- field public static final int Theme_Quantum_Dialog = 16974353; // 0x1030211
- field public static final int Theme_Quantum_DialogWhenLarge = 16974357; // 0x1030215
- field public static final int Theme_Quantum_DialogWhenLarge_NoActionBar = 16974358; // 0x1030216
- field public static final int Theme_Quantum_Dialog_MinWidth = 16974354; // 0x1030212
- field public static final int Theme_Quantum_Dialog_NoActionBar = 16974355; // 0x1030213
- field public static final int Theme_Quantum_Dialog_NoActionBar_MinWidth = 16974356; // 0x1030214
- field public static final int Theme_Quantum_InputMethod = 16974359; // 0x1030217
- field public static final int Theme_Quantum_Light = 16974367; // 0x103021f
- field public static final int Theme_Quantum_Light_DarkActionBar = 16974368; // 0x1030220
- field public static final int Theme_Quantum_Light_Dialog = 16974369; // 0x1030221
- field public static final int Theme_Quantum_Light_DialogWhenLarge = 16974373; // 0x1030225
- field public static final int Theme_Quantum_Light_DialogWhenLarge_NoActionBar = 16974374; // 0x1030226
- field public static final int Theme_Quantum_Light_Dialog_MinWidth = 16974370; // 0x1030222
- field public static final int Theme_Quantum_Light_Dialog_NoActionBar = 16974371; // 0x1030223
- field public static final int Theme_Quantum_Light_Dialog_NoActionBar_MinWidth = 16974372; // 0x1030224
- field public static final int Theme_Quantum_Light_NoActionBar = 16974375; // 0x1030227
- field public static final int Theme_Quantum_Light_NoActionBar_Fullscreen = 16974376; // 0x1030228
- field public static final int Theme_Quantum_Light_NoActionBar_Overscan = 16974377; // 0x1030229
- field public static final int Theme_Quantum_Light_NoActionBar_TranslucentDecor = 16974378; // 0x103022a
- field public static final int Theme_Quantum_Light_Panel = 16974379; // 0x103022b
- field public static final int Theme_Quantum_NoActionBar = 16974360; // 0x1030218
- field public static final int Theme_Quantum_NoActionBar_Fullscreen = 16974361; // 0x1030219
- field public static final int Theme_Quantum_NoActionBar_Overscan = 16974362; // 0x103021a
- field public static final int Theme_Quantum_NoActionBar_TranslucentDecor = 16974363; // 0x103021b
- field public static final int Theme_Quantum_Panel = 16974364; // 0x103021c
- field public static final int Theme_Quantum_Wallpaper = 16974365; // 0x103021d
- field public static final int Theme_Quantum_Wallpaper_NoTitleBar = 16974366; // 0x103021e
+ field public static final int Theme_Quantum = 16974380; // 0x103022c
+ field public static final int Theme_Quantum_Dialog = 16974381; // 0x103022d
+ field public static final int Theme_Quantum_DialogWhenLarge = 16974385; // 0x1030231
+ field public static final int Theme_Quantum_DialogWhenLarge_NoActionBar = 16974386; // 0x1030232
+ field public static final int Theme_Quantum_Dialog_MinWidth = 16974382; // 0x103022e
+ field public static final int Theme_Quantum_Dialog_NoActionBar = 16974383; // 0x103022f
+ field public static final int Theme_Quantum_Dialog_NoActionBar_MinWidth = 16974384; // 0x1030230
+ field public static final int Theme_Quantum_InputMethod = 16974387; // 0x1030233
+ field public static final int Theme_Quantum_Light = 16974395; // 0x103023b
+ field public static final int Theme_Quantum_Light_DarkActionBar = 16974396; // 0x103023c
+ field public static final int Theme_Quantum_Light_Dialog = 16974397; // 0x103023d
+ field public static final int Theme_Quantum_Light_DialogWhenLarge = 16974401; // 0x1030241
+ field public static final int Theme_Quantum_Light_DialogWhenLarge_NoActionBar = 16974402; // 0x1030242
+ field public static final int Theme_Quantum_Light_Dialog_MinWidth = 16974398; // 0x103023e
+ field public static final int Theme_Quantum_Light_Dialog_NoActionBar = 16974399; // 0x103023f
+ field public static final int Theme_Quantum_Light_Dialog_NoActionBar_MinWidth = 16974400; // 0x1030240
+ field public static final int Theme_Quantum_Light_NoActionBar = 16974403; // 0x1030243
+ field public static final int Theme_Quantum_Light_NoActionBar_Fullscreen = 16974404; // 0x1030244
+ field public static final int Theme_Quantum_Light_NoActionBar_Overscan = 16974405; // 0x1030245
+ field public static final int Theme_Quantum_Light_NoActionBar_TranslucentDecor = 16974406; // 0x1030246
+ field public static final int Theme_Quantum_Light_Panel = 16974407; // 0x1030247
+ field public static final int Theme_Quantum_NoActionBar = 16974388; // 0x1030234
+ field public static final int Theme_Quantum_NoActionBar_Fullscreen = 16974389; // 0x1030235
+ field public static final int Theme_Quantum_NoActionBar_Overscan = 16974390; // 0x1030236
+ field public static final int Theme_Quantum_NoActionBar_TranslucentDecor = 16974391; // 0x1030237
+ field public static final int Theme_Quantum_Panel = 16974392; // 0x1030238
+ field public static final int Theme_Quantum_Wallpaper = 16974393; // 0x1030239
+ field public static final int Theme_Quantum_Wallpaper_NoTitleBar = 16974394; // 0x103023a
field public static final int Theme_Translucent = 16973839; // 0x103000f
field public static final int Theme_Translucent_NoTitleBar = 16973840; // 0x1030010
field public static final int Theme_Translucent_NoTitleBar_Fullscreen = 16973841; // 0x1030011
@@ -1954,26 +2044,26 @@
field public static final int Widget_DeviceDefault_DropDownItem_Spinner = 16974178; // 0x1030162
field public static final int Widget_DeviceDefault_EditText = 16974154; // 0x103014a
field public static final int Widget_DeviceDefault_ExpandableListView = 16974155; // 0x103014b
- field public static final int Widget_DeviceDefault_FastScroll = 16974316; // 0x10301ec
- field public static final int Widget_DeviceDefault_FragmentBreadCrumbs = 16974311; // 0x10301e7
+ field public static final int Widget_DeviceDefault_FastScroll = 16974344; // 0x1030208
+ field public static final int Widget_DeviceDefault_FragmentBreadCrumbs = 16974339; // 0x1030203
field public static final int Widget_DeviceDefault_GridView = 16974156; // 0x103014c
field public static final int Widget_DeviceDefault_HorizontalScrollView = 16974171; // 0x103015b
field public static final int Widget_DeviceDefault_ImageButton = 16974157; // 0x103014d
field public static final int Widget_DeviceDefault_Light = 16974196; // 0x1030174
field public static final int Widget_DeviceDefault_Light_ActionBar = 16974243; // 0x10301a3
field public static final int Widget_DeviceDefault_Light_ActionBar_Solid = 16974247; // 0x10301a7
- field public static final int Widget_DeviceDefault_Light_ActionBar_Solid_Inverse = 16974248; // 0x10301a8
+ field public static final deprecated int Widget_DeviceDefault_Light_ActionBar_Solid_Inverse = 16974248; // 0x10301a8
field public static final int Widget_DeviceDefault_Light_ActionBar_TabBar = 16974246; // 0x10301a6
- field public static final int Widget_DeviceDefault_Light_ActionBar_TabBar_Inverse = 16974249; // 0x10301a9
+ field public static final deprecated int Widget_DeviceDefault_Light_ActionBar_TabBar_Inverse = 16974249; // 0x10301a9
field public static final int Widget_DeviceDefault_Light_ActionBar_TabText = 16974245; // 0x10301a5
- field public static final int Widget_DeviceDefault_Light_ActionBar_TabText_Inverse = 16974251; // 0x10301ab
+ field public static final deprecated int Widget_DeviceDefault_Light_ActionBar_TabText_Inverse = 16974251; // 0x10301ab
field public static final int Widget_DeviceDefault_Light_ActionBar_TabView = 16974244; // 0x10301a4
- field public static final int Widget_DeviceDefault_Light_ActionBar_TabView_Inverse = 16974250; // 0x10301aa
+ field public static final deprecated int Widget_DeviceDefault_Light_ActionBar_TabView_Inverse = 16974250; // 0x10301aa
field public static final int Widget_DeviceDefault_Light_ActionButton = 16974239; // 0x103019f
field public static final int Widget_DeviceDefault_Light_ActionButton_CloseMode = 16974242; // 0x10301a2
field public static final int Widget_DeviceDefault_Light_ActionButton_Overflow = 16974240; // 0x10301a0
field public static final int Widget_DeviceDefault_Light_ActionMode = 16974241; // 0x10301a1
- field public static final int Widget_DeviceDefault_Light_ActionMode_Inverse = 16974252; // 0x10301ac
+ field public static final deprecated int Widget_DeviceDefault_Light_ActionMode_Inverse = 16974252; // 0x10301ac
field public static final int Widget_DeviceDefault_Light_AutoCompleteTextView = 16974203; // 0x103017b
field public static final int Widget_DeviceDefault_Light_Button = 16974197; // 0x1030175
field public static final int Widget_DeviceDefault_Light_Button_Borderless_Small = 16974201; // 0x1030179
@@ -1989,8 +2079,8 @@
field public static final int Widget_DeviceDefault_Light_DropDownItem_Spinner = 16974233; // 0x1030199
field public static final int Widget_DeviceDefault_Light_EditText = 16974206; // 0x103017e
field public static final int Widget_DeviceDefault_Light_ExpandableListView = 16974207; // 0x103017f
- field public static final int Widget_DeviceDefault_Light_FastScroll = 16974317; // 0x10301ed
- field public static final int Widget_DeviceDefault_Light_FragmentBreadCrumbs = 16974312; // 0x10301e8
+ field public static final int Widget_DeviceDefault_Light_FastScroll = 16974345; // 0x1030209
+ field public static final int Widget_DeviceDefault_Light_FragmentBreadCrumbs = 16974340; // 0x1030204
field public static final int Widget_DeviceDefault_Light_GridView = 16974208; // 0x1030180
field public static final int Widget_DeviceDefault_Light_HorizontalScrollView = 16974226; // 0x1030192
field public static final int Widget_DeviceDefault_Light_ImageButton = 16974209; // 0x1030181
@@ -2047,7 +2137,7 @@
field public static final int Widget_DropDownItem_Spinner = 16973868; // 0x103002c
field public static final int Widget_EditText = 16973859; // 0x1030023
field public static final int Widget_ExpandableListView = 16973860; // 0x1030024
- field public static final int Widget_FastScroll = 16974313; // 0x10301e9
+ field public static final int Widget_FastScroll = 16974341; // 0x1030205
field public static final int Widget_FragmentBreadCrumbs = 16973961; // 0x1030089
field public static final int Widget_Gallery = 16973877; // 0x1030035
field public static final int Widget_GridView = 16973874; // 0x1030032
@@ -2079,8 +2169,8 @@
field public static final int Widget_Holo_DropDownItem_Spinner = 16973995; // 0x10300ab
field public static final int Widget_Holo_EditText = 16973971; // 0x1030093
field public static final int Widget_Holo_ExpandableListView = 16973972; // 0x1030094
- field public static final int Widget_Holo_FastScroll = 16974314; // 0x10301ea
- field public static final int Widget_Holo_FragmentBreadCrumbs = 16974309; // 0x10301e5
+ field public static final int Widget_Holo_FastScroll = 16974342; // 0x1030206
+ field public static final int Widget_Holo_FragmentBreadCrumbs = 16974337; // 0x1030201
field public static final int Widget_Holo_GridView = 16973973; // 0x1030095
field public static final int Widget_Holo_HorizontalScrollView = 16973988; // 0x10300a4
field public static final int Widget_Holo_ImageButton = 16973974; // 0x1030096
@@ -2101,6 +2191,7 @@
field public static final int Widget_Holo_Light_ActionMode_Inverse = 16974119; // 0x1030127
field public static final int Widget_Holo_Light_AutoCompleteTextView = 16974011; // 0x10300bb
field public static final int Widget_Holo_Light_Button = 16974006; // 0x10300b6
+ field public static final int Widget_Holo_Light_Button_Borderless = 16974542; // 0x10302ce
field public static final int Widget_Holo_Light_Button_Borderless_Small = 16974107; // 0x103011b
field public static final int Widget_Holo_Light_Button_Inset = 16974008; // 0x10300b8
field public static final int Widget_Holo_Light_Button_Small = 16974007; // 0x10300b7
@@ -2114,8 +2205,8 @@
field public static final int Widget_Holo_Light_DropDownItem_Spinner = 16974041; // 0x10300d9
field public static final int Widget_Holo_Light_EditText = 16974014; // 0x10300be
field public static final int Widget_Holo_Light_ExpandableListView = 16974015; // 0x10300bf
- field public static final int Widget_Holo_Light_FastScroll = 16974315; // 0x10301eb
- field public static final int Widget_Holo_Light_FragmentBreadCrumbs = 16974310; // 0x10301e6
+ field public static final int Widget_Holo_Light_FastScroll = 16974343; // 0x1030207
+ field public static final int Widget_Holo_Light_FragmentBreadCrumbs = 16974338; // 0x1030202
field public static final int Widget_Holo_Light_GridView = 16974016; // 0x10300c0
field public static final int Widget_Holo_Light_HorizontalScrollView = 16974034; // 0x10300d2
field public static final int Widget_Holo_Light_ImageButton = 16974017; // 0x10300c1
@@ -2185,127 +2276,128 @@
field public static final int Widget_ProgressBar_Large_Inverse = 16973916; // 0x103005c
field public static final int Widget_ProgressBar_Small = 16973854; // 0x103001e
field public static final int Widget_ProgressBar_Small_Inverse = 16973917; // 0x103005d
- field public static final int Widget_Quantum = 16974380; // 0x103022c
- field public static final int Widget_Quantum_ActionBar = 16974381; // 0x103022d
- field public static final int Widget_Quantum_ActionBar_Solid = 16974382; // 0x103022e
- field public static final int Widget_Quantum_ActionBar_TabBar = 16974383; // 0x103022f
- field public static final int Widget_Quantum_ActionBar_TabText = 16974384; // 0x1030230
- field public static final int Widget_Quantum_ActionBar_TabView = 16974385; // 0x1030231
- field public static final int Widget_Quantum_ActionButton = 16974386; // 0x1030232
- field public static final int Widget_Quantum_ActionButton_CloseMode = 16974387; // 0x1030233
- field public static final int Widget_Quantum_ActionButton_Overflow = 16974388; // 0x1030234
- field public static final int Widget_Quantum_ActionButton_TextButton = 16974389; // 0x1030235
- field public static final int Widget_Quantum_ActionMode = 16974390; // 0x1030236
- field public static final int Widget_Quantum_AutoCompleteTextView = 16974391; // 0x1030237
- field public static final int Widget_Quantum_Button = 16974392; // 0x1030238
- field public static final int Widget_Quantum_Button_Borderless = 16974393; // 0x1030239
- field public static final int Widget_Quantum_Button_Borderless_Small = 16974394; // 0x103023a
- field public static final int Widget_Quantum_Button_Inset = 16974395; // 0x103023b
- field public static final int Widget_Quantum_Button_Paper = 16974503; // 0x10302a7
- field public static final int Widget_Quantum_Button_Paper_Color = 16974504; // 0x10302a8
- field public static final int Widget_Quantum_Button_Small = 16974396; // 0x103023c
- field public static final int Widget_Quantum_Button_Toggle = 16974397; // 0x103023d
- field public static final int Widget_Quantum_CalendarView = 16974398; // 0x103023e
- field public static final int Widget_Quantum_CheckedTextView = 16974399; // 0x103023f
- field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974400; // 0x1030240
- field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974401; // 0x1030241
- field public static final int Widget_Quantum_CompoundButton_Star = 16974402; // 0x1030242
- field public static final int Widget_Quantum_DatePicker = 16974403; // 0x1030243
- field public static final int Widget_Quantum_DropDownItem = 16974404; // 0x1030244
- field public static final int Widget_Quantum_DropDownItem_Spinner = 16974405; // 0x1030245
- field public static final int Widget_Quantum_EditText = 16974406; // 0x1030246
- field public static final int Widget_Quantum_ExpandableListView = 16974407; // 0x1030247
- field public static final int Widget_Quantum_FastScroll = 16974408; // 0x1030248
- field public static final int Widget_Quantum_FragmentBreadCrumbs = 16974409; // 0x1030249
- field public static final int Widget_Quantum_GridView = 16974410; // 0x103024a
- field public static final int Widget_Quantum_HorizontalScrollView = 16974411; // 0x103024b
- field public static final int Widget_Quantum_ImageButton = 16974412; // 0x103024c
- field public static final int Widget_Quantum_Light = 16974436; // 0x1030264
- field public static final int Widget_Quantum_Light_ActionBar = 16974437; // 0x1030265
- field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974438; // 0x1030266
- field public static final int Widget_Quantum_Light_ActionBar_Solid_Inverse = 16974439; // 0x1030267
- field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974440; // 0x1030268
- field public static final int Widget_Quantum_Light_ActionBar_TabBar_Inverse = 16974441; // 0x1030269
- field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974442; // 0x103026a
- field public static final int Widget_Quantum_Light_ActionBar_TabText_Inverse = 16974443; // 0x103026b
- field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974444; // 0x103026c
- field public static final int Widget_Quantum_Light_ActionBar_TabView_Inverse = 16974445; // 0x103026d
- field public static final int Widget_Quantum_Light_ActionButton = 16974446; // 0x103026e
- field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974447; // 0x103026f
- field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974448; // 0x1030270
- field public static final int Widget_Quantum_Light_ActionMode = 16974450; // 0x1030272
- field public static final int Widget_Quantum_Light_ActionMode_Inverse = 16974449; // 0x1030271
- field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974451; // 0x1030273
- field public static final int Widget_Quantum_Light_Button = 16974452; // 0x1030274
- field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974453; // 0x1030275
- field public static final int Widget_Quantum_Light_Button_Inset = 16974454; // 0x1030276
- field public static final int Widget_Quantum_Light_Button_Paper = 16974505; // 0x10302a9
- field public static final int Widget_Quantum_Light_Button_Paper_Color = 16974506; // 0x10302aa
- field public static final int Widget_Quantum_Light_Button_Small = 16974455; // 0x1030277
- field public static final int Widget_Quantum_Light_Button_Toggle = 16974456; // 0x1030278
- field public static final int Widget_Quantum_Light_CalendarView = 16974457; // 0x1030279
- field public static final int Widget_Quantum_Light_CheckedTextView = 16974458; // 0x103027a
- field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974459; // 0x103027b
- field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974460; // 0x103027c
- field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974461; // 0x103027d
- field public static final int Widget_Quantum_Light_DropDownItem = 16974462; // 0x103027e
- field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974463; // 0x103027f
- field public static final int Widget_Quantum_Light_EditText = 16974464; // 0x1030280
- field public static final int Widget_Quantum_Light_ExpandableListView = 16974465; // 0x1030281
- field public static final int Widget_Quantum_Light_FastScroll = 16974466; // 0x1030282
- field public static final int Widget_Quantum_Light_FragmentBreadCrumbs = 16974467; // 0x1030283
- field public static final int Widget_Quantum_Light_GridView = 16974468; // 0x1030284
- field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974469; // 0x1030285
- field public static final int Widget_Quantum_Light_ImageButton = 16974470; // 0x1030286
- field public static final int Widget_Quantum_Light_ListPopupWindow = 16974471; // 0x1030287
- field public static final int Widget_Quantum_Light_ListView = 16974472; // 0x1030288
- field public static final int Widget_Quantum_Light_ListView_DropDown = 16974473; // 0x1030289
- field public static final int Widget_Quantum_Light_MediaRouteButton = 16974474; // 0x103028a
- field public static final int Widget_Quantum_Light_PopupMenu = 16974475; // 0x103028b
- field public static final int Widget_Quantum_Light_PopupWindow = 16974476; // 0x103028c
- field public static final int Widget_Quantum_Light_ProgressBar = 16974477; // 0x103028d
- field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974478; // 0x103028e
- field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974479; // 0x103028f
- field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974480; // 0x1030290
- field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974481; // 0x1030291
- field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974482; // 0x1030292
- field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974483; // 0x1030293
- field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974484; // 0x1030294
- field public static final int Widget_Quantum_Light_RatingBar = 16974485; // 0x1030295
- field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974486; // 0x1030296
- field public static final int Widget_Quantum_Light_RatingBar_Small = 16974487; // 0x1030297
- field public static final int Widget_Quantum_Light_ScrollView = 16974488; // 0x1030298
- field public static final int Widget_Quantum_Light_SeekBar = 16974489; // 0x1030299
- field public static final int Widget_Quantum_Light_Spinner = 16974490; // 0x103029a
- field public static final int Widget_Quantum_Light_Tab = 16974491; // 0x103029b
- field public static final int Widget_Quantum_Light_TabWidget = 16974492; // 0x103029c
- field public static final int Widget_Quantum_Light_TextView = 16974493; // 0x103029d
- field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974494; // 0x103029e
- field public static final int Widget_Quantum_Light_WebTextView = 16974495; // 0x103029f
- field public static final int Widget_Quantum_Light_WebView = 16974496; // 0x10302a0
- field public static final int Widget_Quantum_ListPopupWindow = 16974413; // 0x103024d
- field public static final int Widget_Quantum_ListView = 16974414; // 0x103024e
- field public static final int Widget_Quantum_ListView_DropDown = 16974415; // 0x103024f
- field public static final int Widget_Quantum_MediaRouteButton = 16974416; // 0x1030250
- field public static final int Widget_Quantum_PopupMenu = 16974417; // 0x1030251
- field public static final int Widget_Quantum_PopupWindow = 16974418; // 0x1030252
- field public static final int Widget_Quantum_ProgressBar = 16974419; // 0x1030253
- field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974420; // 0x1030254
- field public static final int Widget_Quantum_ProgressBar_Large = 16974421; // 0x1030255
- field public static final int Widget_Quantum_ProgressBar_Small = 16974422; // 0x1030256
- field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974423; // 0x1030257
- field public static final int Widget_Quantum_RatingBar = 16974424; // 0x1030258
- field public static final int Widget_Quantum_RatingBar_Indicator = 16974425; // 0x1030259
- field public static final int Widget_Quantum_RatingBar_Small = 16974426; // 0x103025a
- field public static final int Widget_Quantum_ScrollView = 16974427; // 0x103025b
- field public static final int Widget_Quantum_SeekBar = 16974428; // 0x103025c
- field public static final int Widget_Quantum_Spinner = 16974429; // 0x103025d
- field public static final int Widget_Quantum_Tab = 16974430; // 0x103025e
- field public static final int Widget_Quantum_TabWidget = 16974431; // 0x103025f
- field public static final int Widget_Quantum_TextView = 16974432; // 0x1030260
- field public static final int Widget_Quantum_TextView_SpinnerItem = 16974433; // 0x1030261
- field public static final int Widget_Quantum_WebTextView = 16974434; // 0x1030262
- field public static final int Widget_Quantum_WebView = 16974435; // 0x1030263
+ field public static final int Widget_Quantum = 16974408; // 0x1030248
+ field public static final int Widget_Quantum_ActionBar = 16974409; // 0x1030249
+ field public static final int Widget_Quantum_ActionBar_Solid = 16974410; // 0x103024a
+ field public static final int Widget_Quantum_ActionBar_TabBar = 16974411; // 0x103024b
+ field public static final int Widget_Quantum_ActionBar_TabText = 16974412; // 0x103024c
+ field public static final int Widget_Quantum_ActionBar_TabView = 16974413; // 0x103024d
+ field public static final int Widget_Quantum_ActionButton = 16974414; // 0x103024e
+ field public static final int Widget_Quantum_ActionButton_CloseMode = 16974415; // 0x103024f
+ field public static final int Widget_Quantum_ActionButton_Overflow = 16974416; // 0x1030250
+ field public static final int Widget_Quantum_ActionButton_TextButton = 16974417; // 0x1030251
+ field public static final int Widget_Quantum_ActionMode = 16974418; // 0x1030252
+ field public static final int Widget_Quantum_AutoCompleteTextView = 16974419; // 0x1030253
+ field public static final int Widget_Quantum_Button = 16974420; // 0x1030254
+ field public static final int Widget_Quantum_ButtonBar = 16974426; // 0x103025a
+ field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974427; // 0x103025b
+ field public static final int Widget_Quantum_Button_Borderless = 16974421; // 0x1030255
+ field public static final int Widget_Quantum_Button_Borderless_Small = 16974422; // 0x1030256
+ field public static final int Widget_Quantum_Button_Inset = 16974423; // 0x1030257
+ field public static final int Widget_Quantum_Button_Paper = 16974526; // 0x10302be
+ field public static final int Widget_Quantum_Button_Paper_Color = 16974527; // 0x10302bf
+ field public static final int Widget_Quantum_Button_Small = 16974424; // 0x1030258
+ field public static final int Widget_Quantum_Button_Toggle = 16974425; // 0x1030259
+ field public static final int Widget_Quantum_CalendarView = 16974428; // 0x103025c
+ field public static final int Widget_Quantum_CheckedTextView = 16974429; // 0x103025d
+ field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974430; // 0x103025e
+ field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974431; // 0x103025f
+ field public static final int Widget_Quantum_CompoundButton_Star = 16974432; // 0x1030260
+ field public static final int Widget_Quantum_DatePicker = 16974433; // 0x1030261
+ field public static final int Widget_Quantum_DropDownItem = 16974434; // 0x1030262
+ field public static final int Widget_Quantum_DropDownItem_Spinner = 16974435; // 0x1030263
+ field public static final int Widget_Quantum_EditText = 16974436; // 0x1030264
+ field public static final int Widget_Quantum_ExpandableListView = 16974437; // 0x1030265
+ field public static final int Widget_Quantum_FastScroll = 16974438; // 0x1030266
+ field public static final int Widget_Quantum_FragmentBreadCrumbs = 16974439; // 0x1030267
+ field public static final int Widget_Quantum_GridView = 16974440; // 0x1030268
+ field public static final int Widget_Quantum_HorizontalScrollView = 16974441; // 0x1030269
+ field public static final int Widget_Quantum_ImageButton = 16974442; // 0x103026a
+ field public static final int Widget_Quantum_Light = 16974467; // 0x1030283
+ field public static final int Widget_Quantum_Light_ActionBar = 16974468; // 0x1030284
+ field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974469; // 0x1030285
+ field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974470; // 0x1030286
+ field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974471; // 0x1030287
+ field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974472; // 0x1030288
+ field public static final int Widget_Quantum_Light_ActionButton = 16974473; // 0x1030289
+ field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974474; // 0x103028a
+ field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974475; // 0x103028b
+ field public static final int Widget_Quantum_Light_ActionMode = 16974476; // 0x103028c
+ field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974477; // 0x103028d
+ field public static final int Widget_Quantum_Light_Button = 16974478; // 0x103028e
+ field public static final int Widget_Quantum_Light_ButtonBar = 16974483; // 0x1030293
+ field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974484; // 0x1030294
+ field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974479; // 0x103028f
+ field public static final int Widget_Quantum_Light_Button_Inset = 16974480; // 0x1030290
+ field public static final int Widget_Quantum_Light_Button_Paper = 16974528; // 0x10302c0
+ field public static final int Widget_Quantum_Light_Button_Paper_Color = 16974529; // 0x10302c1
+ field public static final int Widget_Quantum_Light_Button_Small = 16974481; // 0x1030291
+ field public static final int Widget_Quantum_Light_Button_Toggle = 16974482; // 0x1030292
+ field public static final int Widget_Quantum_Light_CalendarView = 16974485; // 0x1030295
+ field public static final int Widget_Quantum_Light_CheckedTextView = 16974486; // 0x1030296
+ field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974487; // 0x1030297
+ field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974488; // 0x1030298
+ field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974489; // 0x1030299
+ field public static final int Widget_Quantum_Light_DropDownItem = 16974490; // 0x103029a
+ field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974491; // 0x103029b
+ field public static final int Widget_Quantum_Light_EditText = 16974492; // 0x103029c
+ field public static final int Widget_Quantum_Light_ExpandableListView = 16974493; // 0x103029d
+ field public static final int Widget_Quantum_Light_FastScroll = 16974494; // 0x103029e
+ field public static final int Widget_Quantum_Light_FragmentBreadCrumbs = 16974495; // 0x103029f
+ field public static final int Widget_Quantum_Light_GridView = 16974496; // 0x10302a0
+ field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974497; // 0x10302a1
+ field public static final int Widget_Quantum_Light_ImageButton = 16974498; // 0x10302a2
+ field public static final int Widget_Quantum_Light_ListPopupWindow = 16974499; // 0x10302a3
+ field public static final int Widget_Quantum_Light_ListView = 16974500; // 0x10302a4
+ field public static final int Widget_Quantum_Light_ListView_DropDown = 16974501; // 0x10302a5
+ field public static final int Widget_Quantum_Light_MediaRouteButton = 16974502; // 0x10302a6
+ field public static final int Widget_Quantum_Light_PopupMenu = 16974503; // 0x10302a7
+ field public static final int Widget_Quantum_Light_PopupWindow = 16974504; // 0x10302a8
+ field public static final int Widget_Quantum_Light_ProgressBar = 16974505; // 0x10302a9
+ field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974506; // 0x10302aa
+ field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974507; // 0x10302ab
+ field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974508; // 0x10302ac
+ field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974509; // 0x10302ad
+ field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974510; // 0x10302ae
+ field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974511; // 0x10302af
+ field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974512; // 0x10302b0
+ field public static final int Widget_Quantum_Light_RatingBar = 16974513; // 0x10302b1
+ field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974514; // 0x10302b2
+ field public static final int Widget_Quantum_Light_RatingBar_Small = 16974515; // 0x10302b3
+ field public static final int Widget_Quantum_Light_ScrollView = 16974516; // 0x10302b4
+ field public static final int Widget_Quantum_Light_SeekBar = 16974517; // 0x10302b5
+ field public static final int Widget_Quantum_Light_SegmentedButton = 16974518; // 0x10302b6
+ field public static final int Widget_Quantum_Light_Spinner = 16974519; // 0x10302b7
+ field public static final int Widget_Quantum_Light_Tab = 16974520; // 0x10302b8
+ field public static final int Widget_Quantum_Light_TabWidget = 16974521; // 0x10302b9
+ field public static final int Widget_Quantum_Light_TextView = 16974522; // 0x10302ba
+ field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974523; // 0x10302bb
+ field public static final int Widget_Quantum_Light_WebTextView = 16974524; // 0x10302bc
+ field public static final int Widget_Quantum_Light_WebView = 16974525; // 0x10302bd
+ field public static final int Widget_Quantum_ListPopupWindow = 16974443; // 0x103026b
+ field public static final int Widget_Quantum_ListView = 16974444; // 0x103026c
+ field public static final int Widget_Quantum_ListView_DropDown = 16974445; // 0x103026d
+ field public static final int Widget_Quantum_MediaRouteButton = 16974446; // 0x103026e
+ field public static final int Widget_Quantum_PopupMenu = 16974447; // 0x103026f
+ field public static final int Widget_Quantum_PopupWindow = 16974448; // 0x1030270
+ field public static final int Widget_Quantum_ProgressBar = 16974449; // 0x1030271
+ field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974450; // 0x1030272
+ field public static final int Widget_Quantum_ProgressBar_Large = 16974451; // 0x1030273
+ field public static final int Widget_Quantum_ProgressBar_Small = 16974452; // 0x1030274
+ field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974453; // 0x1030275
+ field public static final int Widget_Quantum_RatingBar = 16974454; // 0x1030276
+ field public static final int Widget_Quantum_RatingBar_Indicator = 16974455; // 0x1030277
+ field public static final int Widget_Quantum_RatingBar_Small = 16974456; // 0x1030278
+ field public static final int Widget_Quantum_ScrollView = 16974457; // 0x1030279
+ field public static final int Widget_Quantum_SeekBar = 16974458; // 0x103027a
+ field public static final int Widget_Quantum_SegmentedButton = 16974459; // 0x103027b
+ field public static final int Widget_Quantum_Spinner = 16974460; // 0x103027c
+ field public static final int Widget_Quantum_Tab = 16974461; // 0x103027d
+ field public static final int Widget_Quantum_TabWidget = 16974462; // 0x103027e
+ field public static final int Widget_Quantum_TextView = 16974463; // 0x103027f
+ field public static final int Widget_Quantum_TextView_SpinnerItem = 16974464; // 0x1030280
+ field public static final int Widget_Quantum_WebTextView = 16974465; // 0x1030281
+ field public static final int Widget_Quantum_WebView = 16974466; // 0x1030282
field public static final int Widget_RatingBar = 16973857; // 0x1030021
field public static final int Widget_ScrollView = 16973869; // 0x103002d
field public static final int Widget_SeekBar = 16973856; // 0x1030020
@@ -2316,6 +2408,34 @@
field public static final int Widget_TextView_PopupMenu = 16973865; // 0x1030029
field public static final int Widget_TextView_SpinnerItem = 16973866; // 0x103002a
field public static final int Widget_WebView = 16973875; // 0x1030033
+ field public static final int l_resource_pad1 = 16974336; // 0x1030200
+ field public static final int l_resource_pad10 = 16974327; // 0x10301f7
+ field public static final int l_resource_pad11 = 16974326; // 0x10301f6
+ field public static final int l_resource_pad12 = 16974325; // 0x10301f5
+ field public static final int l_resource_pad13 = 16974324; // 0x10301f4
+ field public static final int l_resource_pad14 = 16974323; // 0x10301f3
+ field public static final int l_resource_pad15 = 16974322; // 0x10301f2
+ field public static final int l_resource_pad16 = 16974321; // 0x10301f1
+ field public static final int l_resource_pad17 = 16974320; // 0x10301f0
+ field public static final int l_resource_pad18 = 16974319; // 0x10301ef
+ field public static final int l_resource_pad19 = 16974318; // 0x10301ee
+ field public static final int l_resource_pad2 = 16974335; // 0x10301ff
+ field public static final int l_resource_pad20 = 16974317; // 0x10301ed
+ field public static final int l_resource_pad21 = 16974316; // 0x10301ec
+ field public static final int l_resource_pad22 = 16974315; // 0x10301eb
+ field public static final int l_resource_pad23 = 16974314; // 0x10301ea
+ field public static final int l_resource_pad24 = 16974313; // 0x10301e9
+ field public static final int l_resource_pad25 = 16974312; // 0x10301e8
+ field public static final int l_resource_pad26 = 16974311; // 0x10301e7
+ field public static final int l_resource_pad27 = 16974310; // 0x10301e6
+ field public static final int l_resource_pad28 = 16974309; // 0x10301e5
+ field public static final int l_resource_pad3 = 16974334; // 0x10301fe
+ field public static final int l_resource_pad4 = 16974333; // 0x10301fd
+ field public static final int l_resource_pad5 = 16974332; // 0x10301fc
+ field public static final int l_resource_pad6 = 16974331; // 0x10301fb
+ field public static final int l_resource_pad7 = 16974330; // 0x10301fa
+ field public static final int l_resource_pad8 = 16974329; // 0x10301f9
+ field public static final int l_resource_pad9 = 16974328; // 0x10301f8
}
public static final class R.xml {
@@ -6374,6 +6494,7 @@
field public static final java.lang.String USER_SERVICE = "user";
field public static final java.lang.String VIBRATOR_SERVICE = "vibrator";
field public static final java.lang.String WALLPAPER_SERVICE = "wallpaper";
+ field public static final java.lang.String WIFI_HOTSPOT_SERVICE = "wifihotspot";
field public static final java.lang.String WIFI_P2P_SERVICE = "wifip2p";
field public static final java.lang.String WIFI_SERVICE = "wifi";
field public static final java.lang.String WINDOW_SERVICE = "window";
@@ -6805,6 +6926,7 @@
field public static final java.lang.String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER";
field public static final java.lang.String CATEGORY_LE_DESK_DOCK = "android.intent.category.LE_DESK_DOCK";
field public static final java.lang.String CATEGORY_MONKEY = "android.intent.category.MONKEY";
+ field public static final java.lang.String CATEGORY_NOTIFICATION_PREFERENCES = "android.intent.category.NOTIFICATION_PREFERENCES";
field public static final java.lang.String CATEGORY_OPENABLE = "android.intent.category.OPENABLE";
field public static final java.lang.String CATEGORY_PREFERENCE = "android.intent.category.PREFERENCE";
field public static final java.lang.String CATEGORY_SAMPLE_CODE = "android.intent.category.SAMPLE_CODE";
@@ -10759,10 +10881,6 @@
method public void setPicture(android.graphics.Picture);
}
- public class RevealDrawable extends android.graphics.drawable.LayerDrawable {
- ctor public RevealDrawable(android.graphics.drawable.Drawable[]);
- }
-
public class RotateDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
ctor public RotateDrawable();
method public void draw(android.graphics.Canvas);
@@ -10832,7 +10950,8 @@
method public void addState(int[], android.graphics.drawable.Drawable);
}
- public class TouchFeedbackDrawable extends android.graphics.drawable.DrawableWrapper {
+ public class TouchFeedbackDrawable extends android.graphics.drawable.LayerDrawable {
+ method public android.graphics.Rect getDirtyBounds();
}
public class TransitionDrawable extends android.graphics.drawable.LayerDrawable implements android.graphics.drawable.Drawable.Callback {
@@ -10844,6 +10963,27 @@
method public void startTransition(int);
}
+ public class VectorDrawable extends android.graphics.drawable.Drawable {
+ ctor public VectorDrawable();
+ method public void draw(android.graphics.Canvas);
+ method public float geAnimationFraction();
+ method public int getOpacity();
+ method public int getRepeatCount();
+ method public void setAlpha(int);
+ method public void setAnimationFraction(float);
+ method public void setColorFilter(android.graphics.ColorFilter);
+ method public void setDuration(long);
+ method public void setIntrinsicHeight(int);
+ method public void setIntrinsicWidth(int);
+ method public void setPadding(android.graphics.Rect);
+ method public void setPadding(int, int, int, int);
+ method public void setRepeatCount(int);
+ method public void setRepeatMode(int);
+ method public void start();
+ method public void stop();
+ field public static final int INFINITE = -1; // 0xffffffff
+ }
+
}
package android.graphics.drawable.shapes {
@@ -11577,6 +11717,7 @@
field public static final int FLASH_MODE_TORCH = 2; // 0x2
field public static final int FLASH_STATE_CHARGING = 1; // 0x1
field public static final int FLASH_STATE_FIRED = 3; // 0x3
+ field public static final int FLASH_STATE_PARTIAL = 4; // 0x4
field public static final int FLASH_STATE_READY = 2; // 0x2
field public static final int FLASH_STATE_UNAVAILABLE = 0; // 0x0
field public static final int HOT_PIXEL_MODE_FAST = 1; // 0x1
@@ -11945,11 +12086,16 @@
field public static final int MESSAGE_VENDOR_COMMAND_WITH_ID = 160; // 0xa0
field public static final int MESSAGE_VENDOR_REMOTE_BUTTON_DOWN = 138; // 0x8a
field public static final int MESSAGE_VENDOR_REMOTE_BUTTON_UP = 139; // 0x8b
+ field public static final int POWER_STATUS_ON = 0; // 0x0
+ field public static final int POWER_STATUS_STANDBY = 1; // 0x1
+ field public static final int POWER_STATUS_UNKNOWN = -1; // 0xffffffff
+ field public static final int POWER_TRANSIENT_TO_ON = 2; // 0x2
+ field public static final int POWER_TRANSIENT_TO_STANDBY = 3; // 0x3
}
public final class HdmiCecClient {
+ method public boolean isTvOn();
method public void sendActiveSource();
- method public void sendGiveDevicePowerStatus(int);
method public void sendImageViewOn();
method public void sendInactiveSource();
method public void sendTextViewOn();
@@ -16064,6 +16210,19 @@
}
+package android.net.wifi.hotspot {
+
+ public abstract interface IWifiHotspotManager implements android.os.IInterface {
+ method public abstract void test() throws android.os.RemoteException;
+ }
+
+ public class WifiHotspotManager {
+ ctor public WifiHotspotManager(android.content.Context, android.net.wifi.hotspot.IWifiHotspotManager);
+ method public void test();
+ }
+
+}
+
package android.net.wifi.p2p {
public class WifiP2pConfig implements android.os.Parcelable {
@@ -22123,6 +22282,7 @@
field public static final java.lang.String EXTRA_MEDIA_ARTIST = "android.intent.extra.artist";
field public static final java.lang.String EXTRA_MEDIA_FOCUS = "android.intent.extra.focus";
field public static final java.lang.String EXTRA_MEDIA_GENRE = "android.intent.extra.genre";
+ field public static final java.lang.String EXTRA_MEDIA_PLAYLIST = "android.intent.extra.playlist";
field public static final java.lang.String EXTRA_MEDIA_RADIO_CHANNEL = "android.intent.extra.radio_channel";
field public static final java.lang.String EXTRA_MEDIA_TITLE = "android.intent.extra.title";
field public static final java.lang.String EXTRA_OUTPUT = "output";
@@ -24182,8 +24342,12 @@
ctor public NotificationListenerService();
method public final void cancelAllNotifications();
method public final void cancelNotification(java.lang.String, java.lang.String, int);
+ method public final void cancelNotifications(java.lang.String[]);
+ method public java.lang.String[] getActiveNotificationKeys();
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
+ method public android.service.notification.StatusBarNotification[] getActiveNotifications(java.lang.String[]);
method public android.os.IBinder onBind(android.content.Intent);
+ method public void onListenerConnected(java.lang.String[]);
method public abstract void onNotificationPosted(android.service.notification.StatusBarNotification);
method public abstract void onNotificationRemoved(android.service.notification.StatusBarNotification);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
@@ -24195,6 +24359,7 @@
method public android.service.notification.StatusBarNotification clone();
method public int describeContents();
method public int getId();
+ method public java.lang.String getKey();
method public android.app.Notification getNotification();
method public java.lang.String getPackageName();
method public long getPostTime();
@@ -24231,6 +24396,20 @@
}
+package android.service.trust {
+
+ public class TrustAgentService extends android.app.Service {
+ ctor public TrustAgentService();
+ method protected final void enableTrust(java.lang.String, long, boolean);
+ method public final android.os.IBinder onBind(android.content.Intent);
+ method protected void onUnlockAttempt(boolean);
+ method protected final void revokeTrust();
+ field public static final java.lang.String SERVICE_INTERFACE = "android.service.trust.TrustAgentService";
+ field public static final java.lang.String TRUST_AGENT_META_DATA = "android.service.trust.trustagent";
+ }
+
+}
+
package android.service.wallpaper {
public abstract class WallpaperService extends android.app.Service {
@@ -27683,9 +27862,9 @@
field public static final java.lang.String GOOD_IRI_CHAR = "a-zA-Z0-9\u00a0-\ud7ff\uf900-\ufdcf\ufdf0-\uffef";
field public static final java.util.regex.Pattern IP_ADDRESS;
field public static final java.util.regex.Pattern PHONE;
- field public static final java.util.regex.Pattern TOP_LEVEL_DOMAIN;
- field public static final java.lang.String TOP_LEVEL_DOMAIN_STR = "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(biz|b[abdefghijmnorstvwyz])|(cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(edu|e[cegrstu])|f[ijkmor]|(gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(info|int|i[delmnoqrst])|(jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(name|net|n[acefgilopruz])|(org|om)|(pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw])";
- field public static final java.lang.String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL = "(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(?:\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw]))";
+ field public static final deprecated java.util.regex.Pattern TOP_LEVEL_DOMAIN;
+ field public static final deprecated java.lang.String TOP_LEVEL_DOMAIN_STR = "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(biz|b[abdefghijmnorstvwyz])|(cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(edu|e[cegrstu])|f[ijkmor]|(gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(info|int|i[delmnoqrst])|(jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(name|net|n[acefgilopruz])|(org|om)|(pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw])";
+ field public static final deprecated java.lang.String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL = "(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnprwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdeghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eosuw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agksyz]|v[aceginu]|w[fs]|(?:\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)|y[et]|z[amw]))";
field public static final java.util.regex.Pattern WEB_URL;
}
@@ -28158,6 +28337,7 @@
method public android.os.Vibrator getVibrator();
method public boolean[] hasKeys(int...);
method public boolean isVirtual();
+ method public boolean supportsSource(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int KEYBOARD_TYPE_ALPHABETIC = 2; // 0x2
@@ -29178,6 +29358,7 @@
method protected int computeVerticalScrollRange();
method public android.view.accessibility.AccessibilityNodeInfo createAccessibilityNodeInfo();
method public void createContextMenu(android.view.ContextMenu);
+ method public final android.animation.ValueAnimator createRevealAnimator(int, int, float, float);
method public void destroyDrawingCache();
method public android.view.WindowInsets dispatchApplyWindowInsets(android.view.WindowInsets);
method public void dispatchConfigurationChanged(android.content.res.Configuration);
diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk
index cb7e1a0..7c25354 100644
--- a/cmds/app_process/Android.mk
+++ b/cmds/app_process/Android.mk
@@ -14,30 +14,11 @@
libandroid_runtime
LOCAL_MODULE:= app_process
-LOCAL_32_BIT_ONLY := true
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := app_process
+LOCAL_MODULE_STEM_64 := app_process64
include $(BUILD_EXECUTABLE)
-ifeq ($(TARGET_IS_64_BIT),true)
-
-# 64-bit app_process64
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- app_main.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
- liblog \
- libbinder \
- libandroid_runtime
-
-LOCAL_MODULE:= app_process64
-LOCAL_NO_2ND_ARCH := true
-include $(BUILD_EXECUTABLE)
-
-endif # TARGET_IS_64_BIT
-
# Build a variant of app_process binary linked with ASan runtime.
# ARM-only at the moment.
ifeq ($(TARGET_ARCH),arm)
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 8d2b739..bdbb08c 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -30,8 +30,9 @@
class AppRuntime : public AndroidRuntime
{
public:
- AppRuntime()
- : mParentDir(NULL)
+ AppRuntime(char* argBlockStart, const size_t argBlockLength)
+ : AndroidRuntime(argBlockStart, argBlockLength)
+ , mParentDir(NULL)
, mClassName(NULL)
, mClass(NULL)
, mArgC(0)
@@ -125,29 +126,30 @@
using namespace android;
-/*
- * sets argv0 to as much of newArgv0 as will fit
- */
-static void setArgv0(const char *argv0, const char *newArgv0)
-{
- strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
+static size_t computeArgBlockSize(int argc, char* const argv[]) {
+ // TODO: This assumes that all arguments are allocated in
+ // contiguous memory. There isn't any documented guarantee
+ // that this is the case, but this is how the kernel does it
+ // (see fs/exec.c).
+ //
+ // Also note that this is a constant for "normal" android apps.
+ // Since they're forked from zygote, the size of their command line
+ // is the size of the zygote command line.
+ //
+ // We change the process name of the process by over-writing
+ // the start of the argument block (argv[0]) with the new name of
+ // the process, so we'd mysteriously start getting truncated process
+ // names if the zygote command line decreases in size.
+ uintptr_t start = reinterpret_cast<uintptr_t>(argv[0]);
+ uintptr_t end = reinterpret_cast<uintptr_t>(argv[argc - 1]);
+ end += strlen(argv[argc - 1]);
+
+ return (end - start);
}
int main(int argc, char* const argv[])
{
- // These are global variables in ProcessState.cpp
- mArgC = argc;
- mArgV = argv;
-
- mArgLen = 0;
- for (int i=0; i<argc; i++) {
- mArgLen += strlen(argv[i]) + 1;
- }
- mArgLen--;
-
- AppRuntime runtime;
- const char* argv0 = argv[0];
-
+ AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// Process command line arguments
// ignore argv[0]
argc--;
@@ -184,7 +186,7 @@
}
if (niceName && *niceName) {
- setArgv0(argv0, niceName);
+ runtime.setArgv0(niceName);
set_process_name(niceName);
}
diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp
index c5fc941..1153f38 100644
--- a/cmds/idmap/scan.cpp
+++ b/cmds/idmap/scan.cpp
@@ -119,7 +119,8 @@
int parse_manifest(const void *data, size_t size, const char *target_package_name)
{
- ResXMLTree parser(data, size);
+ ResXMLTree parser;
+ parser.setTo(data, size);
if (parser.getError() != NO_ERROR) {
ALOGD("%s failed to init xml parser, error=0x%08x\n", __FUNCTION__, parser.getError());
return -1;
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index d513a10..5454b46 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -25,7 +25,7 @@
import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
-import android.content.pm.IPackageInstallObserver;
+import android.content.pm.IPackageInstallObserver2;
import android.content.pm.IPackageManager;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
@@ -39,6 +39,7 @@
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.net.Uri;
+import android.os.Bundle;
import android.os.IUserManager;
import android.os.Process;
import android.os.RemoteException;
@@ -700,14 +701,23 @@
ActivityManager.dumpPackageStateStatic(FileDescriptor.out, pkg);
}
- class PackageInstallObserver extends IPackageInstallObserver.Stub {
+ class PackageInstallObserver extends IPackageInstallObserver2.Stub {
boolean finished;
int result;
+ String extraPermission;
+ String extraPackage;
- public void packageInstalled(String name, int status) {
+ @Override
+ public void packageInstalled(String name, Bundle extras, int status) {
synchronized( this) {
finished = true;
result = status;
+ if (status == PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION) {
+ extraPermission = extras.getString(
+ PackageManager.EXTRA_FAILURE_EXISTING_PERMISSION);
+ extraPackage = extras.getString(
+ PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
+ }
notifyAll();
}
}
@@ -717,7 +727,8 @@
* Converts a failure code into a string by using reflection to find a matching constant
* in PackageManager.
*/
- private String installFailureToString(int result) {
+ private String installFailureToString(PackageInstallObserver obs) {
+ final int result = obs.result;
Field[] fields = PackageManager.class.getFields();
for (Field f: fields) {
if (f.getType() == int.class) {
@@ -732,7 +743,16 @@
// get the int value and compare it to result.
try {
if (result == f.getInt(null)) {
- return fieldName;
+ StringBuilder sb = new StringBuilder(64);
+ sb.append(fieldName);
+ if (obs.extraPermission != null) {
+ sb.append(" perm=");
+ sb.append(obs.extraPermission);
+ }
+ if (obs.extraPackage != null) {
+ sb.append(" pkg=" + obs.extraPackage);
+ }
+ return sb.toString();
}
} catch (IllegalAccessException e) {
// this shouldn't happen since we only look for public static fields.
@@ -956,7 +976,7 @@
VerificationParams verificationParams = new VerificationParams(verificationURI,
originatingURI, referrerURI, VerificationParams.NO_UID, null);
- mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags,
+ mPm.installPackageWithVerificationAndEncryptionEtc(apkURI, null, obs, installFlags,
installerPackageName, verificationParams, encryptionParams);
synchronized (obs) {
@@ -970,7 +990,7 @@
System.out.println("Success");
} else {
System.err.println("Failure ["
- + installFailureToString(obs.result)
+ + installFailureToString(obs)
+ "]");
}
}
@@ -1013,18 +1033,18 @@
public void runCreateUser() {
String name;
- int relatedUserId = -1;
+ int userId = -1;
int flags = 0;
String opt;
while ((opt = nextOption()) != null) {
- if ("--relatedTo".equals(opt)) {
+ if ("--profileOf".equals(opt)) {
String optionData = nextOptionData();
if (optionData == null || !isNumber(optionData)) {
System.err.println("Error: no USER_ID specified");
showUsage();
return;
} else {
- relatedUserId = Integer.parseInt(optionData);
+ userId = Integer.parseInt(optionData);
}
} else if ("--managed".equals(opt)) {
flags |= UserInfo.FLAG_MANAGED_PROFILE;
@@ -1042,14 +1062,14 @@
name = arg;
try {
UserInfo info = null;
- if (relatedUserId < 0) {
+ if (userId < 0) {
info = mUm.createUser(name, flags);
} else {
if (Process.myUid() != 0) {
System.err.println("Error: not running as root.");
return;
}
- info = mUm.createRelatedUser(name, flags, relatedUserId);
+ info = mUm.createProfileForUser(name, flags, userId);
}
if (info != null) {
System.out.println("Success: created user id " + info.id);
diff --git a/core/java/android/alsa/AlsaCardsParser.java b/core/java/android/alsa/AlsaCardsParser.java
new file mode 100644
index 0000000..f9af979
--- /dev/null
+++ b/core/java/android/alsa/AlsaCardsParser.java
@@ -0,0 +1,116 @@
+/*
+ * 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.alsascan;
+
+import android.util.Slog;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Vector;
+
+/**
+ * @hide Retrieves information from an ALSA "cards" file.
+ */
+public class AlsaCardsParser {
+ private static final String TAG = "AlsaCardsParser";
+
+ private static LineTokenizer tokenizer_ = new LineTokenizer(" :[]");
+
+ public class AlsaCardRecord {
+ public int mCardNum = -1;
+ public String mField1 = "";
+ public String mCardName = "";
+ public String mCardDescription = "";
+
+ public AlsaCardRecord() {}
+
+ public boolean parse(String line, int lineIndex) {
+ int tokenIndex = 0;
+ int delimIndex = 0;
+ if (lineIndex == 0) {
+ // line # (skip)
+ tokenIndex = tokenizer_.nextToken(line, tokenIndex);
+ delimIndex = tokenizer_.nextDelimiter(line, tokenIndex);
+
+ // mField1
+ tokenIndex = tokenizer_.nextToken(line, delimIndex);
+ delimIndex = tokenizer_.nextDelimiter(line, tokenIndex);
+ mField1 = line.substring(tokenIndex, delimIndex);
+
+ // mCardName
+ tokenIndex = tokenizer_.nextToken(line, delimIndex);
+ // delimIndex = tokenizer_.nextDelimiter(line, tokenIndex);
+ mCardName = line.substring(tokenIndex);
+ // done
+ } else if (lineIndex == 1) {
+ tokenIndex = tokenizer_.nextToken(line, 0);
+ if (tokenIndex != -1) {
+ mCardDescription = line.substring(tokenIndex);
+ }
+ }
+
+ return true;
+ }
+
+ public String textFormat() {
+ return mCardName + " : " + mCardDescription;
+ }
+ }
+
+ private Vector<AlsaCardRecord> cardRecords_ = new Vector<AlsaCardRecord>();
+
+ public void scan() {
+ cardRecords_.clear();
+ final String cardsFilePath = "/proc/asound/cards";
+ File cardsFile = new File(cardsFilePath);
+ try {
+ FileReader reader = new FileReader(cardsFile);
+ BufferedReader bufferedReader = new BufferedReader(reader);
+ String line = "";
+ while ((line = bufferedReader.readLine()) != null) {
+ AlsaCardRecord cardRecord = new AlsaCardRecord();
+ cardRecord.parse(line, 0);
+ cardRecord.parse(line = bufferedReader.readLine(), 1);
+ cardRecords_.add(cardRecord);
+ }
+ reader.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public AlsaCardRecord getCardRecordAt(int index) {
+ return cardRecords_.get(index);
+ }
+
+ public int getNumCardRecords() {
+ return cardRecords_.size();
+ }
+
+ public void Log() {
+ int numCardRecs = getNumCardRecords();
+ for (int index = 0; index < numCardRecs; ++index) {
+ Slog.w(TAG, "usb:" + getCardRecordAt(index).textFormat());
+ }
+ }
+
+ public AlsaCardsParser() {}
+}
diff --git a/core/java/android/alsa/AlsaDevicesParser.java b/core/java/android/alsa/AlsaDevicesParser.java
new file mode 100644
index 0000000..3835942
--- /dev/null
+++ b/core/java/android/alsa/AlsaDevicesParser.java
@@ -0,0 +1,240 @@
+/*
+ * 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.alsascan;
+
+import android.util.Slog;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Vector;
+
+/**
+ * @hide
+ * Retrieves information from an ALSA "devices" file.
+ */
+public class AlsaDevicesParser {
+ private static final String TAG = "AlsaDevicesParser";
+
+ private static final int kIndex_CardDeviceField = 5;
+ private static final int kStartIndex_CardNum = 6;
+ private static final int kEndIndex_CardNum = 8; // one past
+ private static final int kStartIndex_DeviceNum = 9;
+ private static final int kEndIndex_DeviceNum = 11; // one past
+ private static final int kStartIndex_Type = 14;
+
+ private static LineTokenizer mTokenizer = new LineTokenizer(" :[]-");
+
+ private boolean mHasCaptureDevices = false;
+ private boolean mHasPlaybackDevices = false;
+ private boolean mHasMIDIDevices = false;
+
+ public class AlsaDeviceRecord {
+ public static final int kDeviceType_Unknown = -1;
+ public static final int kDeviceType_Audio = 0;
+ public static final int kDeviceType_Control = 1;
+ public static final int kDeviceType_MIDI = 2;
+
+ public static final int kDeviceDir_Unknown = -1;
+ public static final int kDeviceDir_Capture = 0;
+ public static final int kDeviceDir_Playback = 1;
+
+ int mCardNum = -1;
+ int mDeviceNum = -1;
+ int mDeviceType = kDeviceType_Unknown;
+ int mDeviceDir = kDeviceDir_Unknown;
+
+ public AlsaDeviceRecord() {
+ }
+
+ public boolean parse(String line) {
+ // "0123456789012345678901234567890"
+ // " 2: [ 0-31]: digital audio playback"
+ // " 3: [ 0-30]: digital audio capture"
+ // " 35: [ 1] : control"
+ // " 36: [ 2- 0]: raw midi"
+
+ final int kToken_LineNum = 0;
+ final int kToken_CardNum = 1;
+ final int kToken_DeviceNum = 2;
+ final int kToken_Type0 = 3; // "digital", "control", "raw"
+ final int kToken_Type1 = 4; // "audio", "midi"
+ final int kToken_Type2 = 5; // "capture", "playback"
+
+ int tokenOffset = 0;
+ int delimOffset = 0;
+ int tokenIndex = kToken_LineNum;
+ while (true) {
+ tokenOffset = mTokenizer.nextToken(line, delimOffset);
+ if (tokenOffset == LineTokenizer.kTokenNotFound) {
+ break; // bail
+ }
+ delimOffset = mTokenizer.nextDelimiter(line, tokenOffset);
+ if (delimOffset == LineTokenizer.kTokenNotFound) {
+ delimOffset = line.length();
+ }
+ String token = line.substring(tokenOffset, delimOffset);
+
+ switch (tokenIndex) {
+ case kToken_LineNum:
+ // ignore
+ break;
+
+ case kToken_CardNum:
+ mCardNum = Integer.parseInt(token);
+ if (line.charAt(delimOffset) != '-') {
+ tokenIndex++; // no device # in the token stream
+ }
+ break;
+
+ case kToken_DeviceNum:
+ mDeviceNum = Integer.parseInt(token);
+ break;
+
+ case kToken_Type0:
+ if (token.equals("digital")) {
+ // NOP
+ } else if (token.equals("control")) {
+ mDeviceType = kDeviceType_Control;
+ } else if (token.equals("raw")) {
+ // NOP
+ }
+ break;
+
+ case kToken_Type1:
+ if (token.equals("audio")) {
+ mDeviceType = kDeviceType_Audio;
+ } else if (token.equals("midi")) {
+ mDeviceType = kDeviceType_MIDI;
+ mHasMIDIDevices = true;
+ }
+ break;
+
+ case kToken_Type2:
+ if (token.equals("capture")) {
+ mDeviceDir = kDeviceDir_Capture;
+ mHasCaptureDevices = true;
+ } else if (token.equals("playback")) {
+ mDeviceDir = kDeviceDir_Playback;
+ mHasPlaybackDevices = true;
+ }
+ break;
+ } // switch (tokenIndex)
+
+ tokenIndex++;
+ } // while (true)
+
+ return true;
+ } // parse()
+
+ public String textFormat() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("[" + mCardNum + ":" + mDeviceNum + "]");
+
+ switch (mDeviceType) {
+ case kDeviceType_Unknown:
+ sb.append(" N/A");
+ break;
+ case kDeviceType_Audio:
+ sb.append(" Audio");
+ break;
+ case kDeviceType_Control:
+ sb.append(" Control");
+ break;
+ case kDeviceType_MIDI:
+ sb.append(" MIDI");
+ break;
+ }
+
+ switch (mDeviceDir) {
+ case kDeviceDir_Unknown:
+ sb.append(" N/A");
+ break;
+ case kDeviceDir_Capture:
+ sb.append(" Capture");
+ break;
+ case kDeviceDir_Playback:
+ sb.append(" Playback");
+ break;
+ }
+
+ return sb.toString();
+ }
+ }
+
+ private Vector<AlsaDeviceRecord>
+ deviceRecords_ = new Vector<AlsaDeviceRecord>();
+
+ private boolean isLineDeviceRecord(String line) {
+ return line.charAt(kIndex_CardDeviceField) == '[';
+ }
+
+ public AlsaDevicesParser() {
+ }
+
+ public int getNumDeviceRecords() {
+ return deviceRecords_.size();
+ }
+
+ public AlsaDeviceRecord getDeviceRecordAt(int index) {
+ return deviceRecords_.get(index);
+ }
+
+ public void Log() {
+ int numDevRecs = getNumDeviceRecords();
+ for (int index = 0; index < numDevRecs; ++index) {
+ Slog.w(TAG, "usb:" + getDeviceRecordAt(index).textFormat());
+ }
+ }
+
+ public boolean hasPlaybackDevices() {
+ return mHasPlaybackDevices;
+ }
+
+ public boolean hasCaptureDevices() {
+ return mHasCaptureDevices;
+ }
+
+ public boolean hasMIDIDevices() {
+ return mHasMIDIDevices;
+ }
+
+ public void scan() {
+ deviceRecords_.clear();
+
+ final String devicesFilePath = "/proc/asound/devices";
+ File devicesFile = new File(devicesFilePath);
+ try {
+ FileReader reader = new FileReader(devicesFile);
+ BufferedReader bufferedReader = new BufferedReader(reader);
+ String line = "";
+ while ((line = bufferedReader.readLine()) != null) {
+ if (isLineDeviceRecord(line)) {
+ AlsaDeviceRecord deviceRecord = new AlsaDeviceRecord();
+ deviceRecord.parse(line);
+ deviceRecords_.add(deviceRecord);
+ }
+ }
+ reader.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+} // class AlsaDevicesParser
+
diff --git a/core/java/android/alsa/LineTokenizer.java b/core/java/android/alsa/LineTokenizer.java
new file mode 100644
index 0000000..c138fc5
--- /dev/null
+++ b/core/java/android/alsa/LineTokenizer.java
@@ -0,0 +1,57 @@
+/*
+ * 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.alsascan;
+
+/**
+ * @hide
+ * Breaks lines in an ALSA "cards" or "devices" file into tokens.
+ * TODO(pmclean) Look into replacing this with String.split().
+ */
+public class LineTokenizer {
+ public static final int kTokenNotFound = -1;
+
+ private String mDelimiters = "";
+
+ public LineTokenizer(String delimiters) {
+ mDelimiters = delimiters;
+ }
+
+ int nextToken(String line, int startIndex) {
+ int len = line.length();
+ int offset = startIndex;
+ for (; offset < len; offset++) {
+ if (mDelimiters.indexOf(line.charAt(offset)) == -1) {
+ // past a delimiter
+ break;
+ }
+ }
+
+ return offset < len ? offset : kTokenNotFound;
+ }
+
+ int nextDelimiter(String line, int startIndex) {
+ int len = line.length();
+ int offset = startIndex;
+ for (; offset < len; offset++) {
+ if (mDelimiters.indexOf(line.charAt(offset)) != -1) {
+ // past a delimiter
+ break;
+ }
+ }
+
+ return offset < len ? offset : kTokenNotFound;
+ }
+}
diff --git a/core/java/android/animation/RevealAnimator.java b/core/java/android/animation/RevealAnimator.java
new file mode 100644
index 0000000..77a536a
--- /dev/null
+++ b/core/java/android/animation/RevealAnimator.java
@@ -0,0 +1,141 @@
+/*
+ * 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.animation;
+
+import android.view.View;
+
+import java.util.ArrayList;
+
+/**
+ * Reveals a View with an animated clipping circle.
+ * The clipping is implemented efficiently by talking to a private reveal API on View.
+ * This hidden class currently only accessed by the {@link android.view.View}.
+ *
+ * @hide
+ */
+public class RevealAnimator extends ValueAnimator {
+ private final static String LOGTAG = "RevealAnimator";
+ private ValueAnimator.AnimatorListener mListener;
+ private ValueAnimator.AnimatorUpdateListener mUpdateListener;
+ private RevealCircle mReuseRevealCircle = new RevealCircle(0);
+ private RevealAnimator(final View clipView, final int x, final int y,
+ float startRadius, float endRadius, final boolean inverseClip) {
+
+ setObjectValues(new RevealCircle(startRadius), new RevealCircle(endRadius));
+ setEvaluator(new RevealCircleEvaluator(mReuseRevealCircle));
+
+ mUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ RevealCircle circle = (RevealCircle) animation.getAnimatedValue();
+ float radius = circle.getRadius();
+ clipView.setRevealClip(true, inverseClip, x, y, radius);
+ }
+ };
+ mListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ clipView.setRevealClip(false, false, 0, 0, 0);
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ clipView.setRevealClip(false, false, 0, 0, 0);
+ }
+ };
+ addUpdateListener(mUpdateListener);
+ addListener(mListener);
+ }
+
+ public static RevealAnimator ofRevealCircle(View clipView, int x, int y,
+ float startRadius, float endRadius, boolean inverseClip) {
+ RevealAnimator anim = new RevealAnimator(clipView, x, y,
+ startRadius, endRadius, inverseClip);
+ return anim;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeAllUpdateListeners() {
+ super.removeAllUpdateListeners();
+ addUpdateListener(mUpdateListener);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeAllListeners() {
+ super.removeAllListeners();
+ addListener(mListener);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ArrayList<AnimatorListener> getListeners() {
+ ArrayList<AnimatorListener> allListeners =
+ (ArrayList<AnimatorListener>) super.getListeners().clone();
+ allListeners.remove(mListener);
+ return allListeners;
+ }
+
+ private class RevealCircle {
+ float mRadius;
+
+ public RevealCircle(float radius) {
+ mRadius = radius;
+ }
+
+ public void setRadius(float radius) {
+ mRadius = radius;
+ }
+
+ public float getRadius() {
+ return mRadius;
+ }
+ }
+
+ private class RevealCircleEvaluator implements TypeEvaluator<RevealCircle> {
+
+ private RevealCircle mRevealCircle;
+
+ public RevealCircleEvaluator() {
+ }
+
+ public RevealCircleEvaluator(RevealCircle reuseCircle) {
+ mRevealCircle = reuseCircle;
+ }
+
+ @Override
+ public RevealCircle evaluate(float fraction, RevealCircle startValue,
+ RevealCircle endValue) {
+ float currentRadius = startValue.mRadius
+ + ((endValue.mRadius - startValue.mRadius) * fraction);
+ if (mRevealCircle == null) {
+ return new RevealCircle(currentRadius);
+ } else {
+ mRevealCircle.setRadius(currentRadius);
+ return mRevealCircle;
+ }
+ }
+ }
+}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 5a08db7..c027e99 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -601,11 +601,11 @@
public static final int RECENT_IGNORE_UNAVAILABLE = 0x0002;
/**
- * Provides a list that also contains recent tasks for user
- * and related users.
+ * Provides a list that contains recent tasks for all
+ * profiles of a user.
* @hide
*/
- public static final int RECENT_INCLUDE_RELATED = 0x0004;
+ public static final int RECENT_INCLUDE_PROFILES = 0x0004;
/**
* Return a list of the tasks that the user has recently launched, with
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 69ada6a..965f815 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1592,10 +1592,10 @@
/**
* Creates the top level resources for the given package.
*/
- Resources getTopLevelResources(String resDir, String[] overlayDirs,
+ Resources getTopLevelResources(String resDir, String[] overlayDirs, String[] libDirs,
int displayId, Configuration overrideConfiguration,
LoadedApk pkgInfo) {
- return mResourcesManager.getTopLevelResources(resDir, overlayDirs, displayId,
+ return mResourcesManager.getTopLevelResources(resDir, overlayDirs, libDirs, displayId,
overrideConfiguration, pkgInfo.getCompatibilityInfo(), null);
}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 8165fa1..6ca5244 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -29,6 +29,7 @@
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageInstallObserver;
+import android.content.pm.IPackageInstallObserver2;
import android.content.pm.IPackageManager;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
@@ -805,7 +806,7 @@
}
Resources r = mContext.mMainThread.getTopLevelResources(
app.uid == Process.myUid() ? app.sourceDir : app.publicSourceDir,
- app.resourceDirs, Display.DEFAULT_DISPLAY, null, mContext.mPackageInfo);
+ app.resourceDirs, null, Display.DEFAULT_DISPLAY, null, mContext.mPackageInfo);
if (r != null) {
return r;
}
@@ -1073,7 +1074,7 @@
public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
String installerPackageName) {
try {
- mPM.installPackage(packageURI, observer, flags, installerPackageName);
+ mPM.installPackageEtc(packageURI, observer, null, flags, installerPackageName);
} catch (RemoteException e) {
// Should never happen!
}
@@ -1084,8 +1085,8 @@
int flags, String installerPackageName, Uri verificationURI,
ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
try {
- mPM.installPackageWithVerification(packageURI, observer, flags, installerPackageName,
- verificationURI, manifestDigest, encryptionParams);
+ mPM.installPackageWithVerificationEtc(packageURI, observer, null, flags,
+ installerPackageName, verificationURI, manifestDigest, encryptionParams);
} catch (RemoteException e) {
// Should never happen!
}
@@ -1096,8 +1097,46 @@
IPackageInstallObserver observer, int flags, String installerPackageName,
VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
try {
- mPM.installPackageWithVerificationAndEncryption(packageURI, observer, flags,
- installerPackageName, verificationParams, encryptionParams);
+ mPM.installPackageWithVerificationAndEncryptionEtc(packageURI, observer, null,
+ flags, installerPackageName, verificationParams, encryptionParams);
+ } catch (RemoteException e) {
+ // Should never happen!
+ }
+ }
+
+ // Expanded observer-API versions
+ @Override
+ public void installPackage(Uri packageURI, PackageInstallObserver observer,
+ int flags, String installerPackageName) {
+ try {
+ mPM.installPackageEtc(packageURI, null, observer.mObserver,
+ flags, installerPackageName);
+ } catch (RemoteException e) {
+ // Should never happen!
+ }
+ }
+
+ @Override
+ public void installPackageWithVerification(Uri packageURI,
+ PackageInstallObserver observer, int flags, String installerPackageName,
+ Uri verificationURI, ManifestDigest manifestDigest,
+ ContainerEncryptionParams encryptionParams) {
+ try {
+ mPM.installPackageWithVerificationEtc(packageURI, null, observer.mObserver, flags,
+ installerPackageName, verificationURI, manifestDigest, encryptionParams);
+ } catch (RemoteException e) {
+ // Should never happen!
+ }
+ }
+
+ @Override
+ public void installPackageWithVerificationAndEncryption(Uri packageURI,
+ PackageInstallObserver observer, int flags, String installerPackageName,
+ VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+ try {
+ mPM.installPackageWithVerificationAndEncryptionEtc(packageURI, null,
+ observer.mObserver, flags, installerPackageName, verificationParams,
+ encryptionParams);
} catch (RemoteException e) {
// Should never happen!
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 87f47a1..7149ab9 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -75,6 +75,8 @@
import android.net.nsd.NsdManager;
import android.net.wifi.IWifiManager;
import android.net.wifi.WifiManager;
+import android.net.wifi.hotspot.IWifiHotspotManager;
+import android.net.wifi.hotspot.WifiHotspotManager;
import android.net.wifi.p2p.IWifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager;
import android.nfc.NfcManager;
@@ -117,6 +119,7 @@
import android.accounts.AccountManager;
import android.accounts.IAccountManager;
import android.app.admin.DevicePolicyManager;
+import android.app.trust.TrustManager;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsService;
@@ -465,7 +468,8 @@
outerContext.getApplicationInfo().targetSdkVersion,
com.android.internal.R.style.Theme_Dialog,
com.android.internal.R.style.Theme_Holo_Dialog,
- com.android.internal.R.style.Theme_DeviceDefault_Dialog)),
+ com.android.internal.R.style.Theme_DeviceDefault_Dialog,
+ com.android.internal.R.style.Theme_DeviceDefault_Light_Dialog)),
ctx.mMainThread.getHandler());
}});
@@ -552,6 +556,13 @@
return new WifiManager(ctx.getOuterContext(), service);
}});
+ registerService(WIFI_HOTSPOT_SERVICE, new ServiceFetcher() {
+ public Object createService(ContextImpl ctx) {
+ IBinder b = ServiceManager.getService(WIFI_HOTSPOT_SERVICE);
+ IWifiHotspotManager service = IWifiHotspotManager.Stub.asInterface(b);
+ return new WifiHotspotManager(ctx.getOuterContext(), service);
+ }});
+
registerService(WIFI_P2P_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(WIFI_P2P_SERVICE);
@@ -612,6 +623,12 @@
return new MediaSessionManager(ctx);
}
});
+ registerService(TRUST_SERVICE, new ServiceFetcher() {
+ public Object createService(ContextImpl ctx) {
+ IBinder b = ServiceManager.getService(TRUST_SERVICE);
+ return new TrustManager(b);
+ }
+ });
}
static ContextImpl getImpl(Context context) {
@@ -2044,8 +2061,9 @@
|| (compatInfo != null && compatInfo.applicationScale
!= resources.getCompatibilityInfo().applicationScale)) {
resources = mResourcesManager.getTopLevelResources(
- packageInfo.getResDir(), packageInfo.getOverlayDirs(), displayId,
- overrideConfiguration, compatInfo, activityToken);
+ packageInfo.getResDir(), packageInfo.getOverlayDirs(),
+ packageInfo.getApplicationInfo().sharedLibraryFiles,
+ displayId, overrideConfiguration, compatInfo, activityToken);
}
}
mResources = resources;
diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl
index 4ca06ed..7036aea 100644
--- a/core/java/android/app/IBackupAgent.aidl
+++ b/core/java/android/app/IBackupAgent.aidl
@@ -124,4 +124,12 @@
int type, String domain, String path, long mode, long mtime,
int token, IBackupManager callbackBinder);
+ /**
+ * Out of band: instruct the agent to crash within the client process. This is used
+ * when the backup infrastructure detects a semantic error post-hoc and needs to
+ * pass the problem back to the app.
+ *
+ * @param message The message to be passed to the agent's application in an exception.
+ */
+ void fail(String message);
}
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 9f933ca..9911467 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -45,7 +45,8 @@
void unregisterListener(in INotificationListener listener, int userid);
void cancelNotificationFromListener(in INotificationListener token, String pkg, String tag, int id);
- void cancelAllNotificationsFromListener(in INotificationListener token);
+ void cancelNotificationsFromListener(in INotificationListener token, in String[] keys);
- StatusBarNotification[] getActiveNotificationsFromListener(in INotificationListener token);
+ StatusBarNotification[] getActiveNotificationsFromListener(in INotificationListener token, in String[] keys);
+ String[] getActiveNotificationKeysFromListener(in INotificationListener token);
}
\ No newline at end of file
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index d409352..3ae8bfc 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -41,6 +41,7 @@
import android.os.UserHandle;
import android.util.AndroidRuntimeException;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.DisplayAdjustments;
import android.view.Display;
@@ -48,6 +49,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.Enumeration;
@@ -485,7 +488,7 @@
public Resources getResources(ActivityThread mainThread) {
if (mResources == null) {
mResources = mainThread.getTopLevelResources(mResDir, mOverlayDirs,
- Display.DEFAULT_DISPLAY, null, this);
+ mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY, null, this);
}
return mResources;
}
@@ -530,10 +533,101 @@
}
}
}
-
+
+ // Rewrite the R 'constants' for all library apks.
+ SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
+ .getAssignedPackageIdentifiers();
+ final int N = packageIdentifiers.size();
+ for (int i = 0; i < N; i++) {
+ final int id = packageIdentifiers.keyAt(i);
+ if (id == 0x01 || id == 0x7f) {
+ continue;
+ }
+
+ rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
+ }
+
return app;
}
+ private void rewriteIntField(Field field, int packageId) throws IllegalAccessException {
+ int requiredModifiers = Modifier.STATIC | Modifier.PUBLIC;
+ int bannedModifiers = Modifier.FINAL;
+
+ int mod = field.getModifiers();
+ if ((mod & requiredModifiers) != requiredModifiers ||
+ (mod & bannedModifiers) != 0) {
+ throw new IllegalArgumentException("Field " + field.getName() +
+ " is not rewritable");
+ }
+
+ if (field.getType() != int.class && field.getType() != Integer.class) {
+ throw new IllegalArgumentException("Field " + field.getName() +
+ " is not an integer");
+ }
+
+ try {
+ int resId = field.getInt(null);
+ field.setInt(null, (resId & 0x00ffffff) | (packageId << 24));
+ } catch (IllegalAccessException e) {
+ // This should not occur (we check above if we can write to it)
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ private void rewriteIntArrayField(Field field, int packageId) {
+ int requiredModifiers = Modifier.STATIC | Modifier.PUBLIC;
+
+ if ((field.getModifiers() & requiredModifiers) != requiredModifiers) {
+ throw new IllegalArgumentException("Field " + field.getName() +
+ " is not rewritable");
+ }
+
+ if (field.getType() != int[].class) {
+ throw new IllegalArgumentException("Field " + field.getName() +
+ " is not an integer array");
+ }
+
+ try {
+ int[] array = (int[]) field.get(null);
+ for (int i = 0; i < array.length; i++) {
+ array[i] = (array[i] & 0x00ffffff) | (packageId << 24);
+ }
+ } catch (IllegalAccessException e) {
+ // This should not occur (we check above if we can write to it)
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ private void rewriteRValues(ClassLoader cl, String packageName, int id) {
+ try {
+ final Class<?> rClazz = cl.loadClass(packageName + ".R");
+ Class<?>[] declaredClasses = rClazz.getDeclaredClasses();
+ for (Class<?> clazz : declaredClasses) {
+ try {
+ if (clazz.getSimpleName().equals("styleable")) {
+ for (Field field : clazz.getDeclaredFields()) {
+ if (field.getType() == int[].class) {
+ rewriteIntArrayField(field, id);
+ }
+ }
+
+ } else {
+ for (Field field : clazz.getDeclaredFields()) {
+ rewriteIntField(field, id);
+ }
+ }
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Failed to rewrite R values for " +
+ clazz.getName(), e);
+ }
+ }
+
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Failed to rewrite R values", e);
+ }
+ }
+
public void removeContextRegistrations(Context context,
String who, String what) {
final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 13e74da..36d2635 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -17,12 +17,14 @@
package android.app;
import com.android.internal.R;
+import com.android.internal.util.LegacyNotificationUtil;
import android.annotation.IntDef;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.PorterDuff;
import android.media.AudioManager;
import android.net.Uri;
import android.os.BadParcelableException;
@@ -653,13 +655,6 @@
public static final String EXTRA_AS_HEADS_UP = "headsup";
/**
- * Extra added from {@link Notification.Builder} to indicate that the remote views were inflated
- * from the builder, as opposed to being created directly from the application.
- * @hide
- */
- public static final String EXTRA_BUILDER_REMOTE_VIEWS = "android.builderRemoteViews";
-
- /**
* Allow certain system-generated notifications to appear before the device is provisioned.
* Only available to notifications coming from the android package.
* @hide
@@ -1315,6 +1310,7 @@
private int mVisibility = VISIBILITY_PRIVATE;
private Notification mPublicVersion = null;
private boolean mQuantumTheme;
+ private final LegacyNotificationUtil mLegacyNotificationUtil;
/**
* Constructs a new Builder with the defaults:
@@ -1345,6 +1341,10 @@
// 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();
}
/**
@@ -1846,42 +1846,50 @@
boolean showLine3 = false;
boolean showLine2 = false;
int smallIconImageViewId = R.id.icon;
- if (mLargeIcon != null) {
- contentView.setImageViewBitmap(R.id.icon, mLargeIcon);
- smallIconImageViewId = R.id.right_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 (mLargeIcon != null) {
+ contentView.setImageViewBitmap(R.id.icon, mLargeIcon);
+ processLegacyLargeIcon(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);
+ } else {
+ processLegacyLargeIcon(mSmallIcon, contentView);
+ }
+
} else {
contentView.setViewVisibility(smallIconImageViewId, View.GONE);
}
if (mContentTitle != null) {
- contentView.setTextViewText(R.id.title, mContentTitle);
+ contentView.setTextViewText(R.id.title, processLegacyText(mContentTitle));
}
if (mContentText != null) {
- contentView.setTextViewText(R.id.text, mContentText);
+ contentView.setTextViewText(R.id.text, processLegacyText(mContentText));
showLine3 = true;
}
if (mContentInfo != null) {
- contentView.setTextViewText(R.id.info, mContentInfo);
+ contentView.setTextViewText(R.id.info, processLegacyText(mContentInfo));
contentView.setViewVisibility(R.id.info, View.VISIBLE);
showLine3 = true;
} else if (mNumber > 0) {
final int tooBig = mContext.getResources().getInteger(
R.integer.status_bar_notification_info_maxnum);
if (mNumber > tooBig) {
- contentView.setTextViewText(R.id.info, mContext.getResources().getString(
- R.string.status_bar_notification_info_overflow));
+ contentView.setTextViewText(R.id.info, processLegacyText(
+ mContext.getResources().getString(
+ R.string.status_bar_notification_info_overflow)));
} else {
NumberFormat f = NumberFormat.getIntegerInstance();
- contentView.setTextViewText(R.id.info, f.format(mNumber));
+ contentView.setTextViewText(R.id.info, processLegacyText(f.format(mNumber)));
}
contentView.setViewVisibility(R.id.info, View.VISIBLE);
showLine3 = true;
@@ -1891,9 +1899,9 @@
// Need to show three lines?
if (mSubText != null) {
- contentView.setTextViewText(R.id.text, mSubText);
+ contentView.setTextViewText(R.id.text, processLegacyText(mSubText));
if (mContentText != null) {
- contentView.setTextViewText(R.id.text2, mContentText);
+ contentView.setTextViewText(R.id.text2, processLegacyText(mContentText));
contentView.setViewVisibility(R.id.text2, View.VISIBLE);
showLine2 = true;
} else {
@@ -2001,15 +2009,78 @@
tombstone ? getActionTombstoneLayoutResource()
: getActionLayoutResource());
button.setTextViewCompoundDrawablesRelative(R.id.action0, action.icon, 0, 0, 0);
- button.setTextViewText(R.id.action0, action.title);
+ button.setTextViewText(R.id.action0, processLegacyText(action.title));
if (!tombstone) {
button.setOnClickPendingIntent(R.id.action0, action.actionIntent);
}
button.setContentDescription(R.id.action0, action.title);
+ processLegacyAction(action, button);
return button;
}
/**
+ * @return Whether we are currently building a notification from a legacy (an app that
+ * doesn't create quantum notifications by itself) app.
+ */
+ private boolean isLegacy() {
+ return mLegacyNotificationUtil != null;
+ }
+
+ private void processLegacyAction(Action action, RemoteViews button) {
+ if (isLegacy()) {
+ if (mLegacyNotificationUtil.isGrayscale(mContext, action.icon)) {
+ button.setTextViewCompoundDrawablesRelativeColorFilter(R.id.action0, 0,
+ mContext.getResources().getColor(
+ R.color.notification_action_legacy_color_filter),
+ PorterDuff.Mode.MULTIPLY);
+ }
+ }
+ }
+
+ private CharSequence processLegacyText(CharSequence charSequence) {
+ if (isLegacy()) {
+ return mLegacyNotificationUtil.invertCharSequenceColors(charSequence);
+ } else {
+ return charSequence;
+ }
+ }
+
+ private void processLegacyLargeIcon(int largeIconId, RemoteViews contentView) {
+ if (isLegacy()) {
+ processLegacyLargeIcon(
+ mLegacyNotificationUtil.isGrayscale(mContext, largeIconId),
+ contentView);
+ }
+ }
+
+ private void processLegacyLargeIcon(Bitmap largeIcon, RemoteViews contentView) {
+ if (isLegacy()) {
+ processLegacyLargeIcon(
+ mLegacyNotificationUtil.isGrayscale(largeIcon),
+ contentView);
+ }
+ }
+
+ private void processLegacyLargeIcon(boolean isGrayscale, RemoteViews contentView) {
+ if (isLegacy() && isGrayscale) {
+ contentView.setInt(R.id.icon, "setBackgroundResource",
+ R.drawable.notification_icon_legacy_bg_inset);
+ }
+ }
+
+ private void processLegacySmallIcon(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);
+ }
+ }
+ }
+
+ /**
* Apply the unstyled operations and return a new {@link Notification} object.
* @hide
*/
@@ -2075,7 +2146,6 @@
extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mProgressIndeterminate);
extras.putBoolean(EXTRA_SHOW_CHRONOMETER, mUseChronometer);
extras.putBoolean(EXTRA_SHOW_WHEN, mShowWhen);
- extras.putBoolean(EXTRA_BUILDER_REMOTE_VIEWS, mContentView == null);
if (mLargeIcon != null) {
extras.putParcelable(EXTRA_LARGE_ICON, mLargeIcon);
}
@@ -2226,7 +2296,7 @@
mSummaryTextSet ? mSummaryText
: mBuilder.mSubText;
if (overflowText != null) {
- contentView.setTextViewText(R.id.text, overflowText);
+ contentView.setTextViewText(R.id.text, mBuilder.processLegacyText(overflowText));
contentView.setViewVisibility(R.id.overflow_divider, View.VISIBLE);
contentView.setViewVisibility(R.id.line3, View.VISIBLE);
} else {
@@ -2437,7 +2507,7 @@
contentView.setViewPadding(R.id.line1, 0, 0, 0, 0);
}
- contentView.setTextViewText(R.id.big_text, mBigText);
+ contentView.setTextViewText(R.id.big_text, mBuilder.processLegacyText(mBigText));
contentView.setViewVisibility(R.id.big_text, View.VISIBLE);
contentView.setViewVisibility(R.id.text2, View.GONE);
@@ -2542,7 +2612,7 @@
CharSequence str = mTexts.get(i);
if (str != null && !str.equals("")) {
contentView.setViewVisibility(rowIds[i], View.VISIBLE);
- contentView.setTextViewText(rowIds[i], str);
+ contentView.setTextViewText(rowIds[i], mBuilder.processLegacyText(str));
}
i++;
}
diff --git a/core/java/android/app/PackageInstallObserver.java b/core/java/android/app/PackageInstallObserver.java
new file mode 100644
index 0000000..dacffb4
--- /dev/null
+++ b/core/java/android/app/PackageInstallObserver.java
@@ -0,0 +1,49 @@
+/*
+ * 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.pm.IPackageInstallObserver2;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+/**
+ * @hide
+ *
+ * New-style observer for package installers to use.
+ */
+public class PackageInstallObserver {
+ IPackageInstallObserver2.Stub mObserver = new IPackageInstallObserver2.Stub() {
+ @Override
+ public void packageInstalled(String pkgName, Bundle extras, int result)
+ throws RemoteException {
+ PackageInstallObserver.this.packageInstalled(pkgName, extras, result);
+ }
+ };
+
+ /**
+ * This method will be called to report the result of the package installation attempt.
+ *
+ * @param pkgName Name of the package whose installation was attempted
+ * @param extras If non-null, this Bundle contains extras providing additional information
+ * about an install failure. See {@link android.content.pm.PackageManager} for
+ * documentation about which extras apply to various failures; in particular the
+ * strings named EXTRA_FAILURE_*.
+ * @param result The numeric success or failure code indicating the basic outcome
+ */
+ public void packageInstalled(String pkgName, Bundle extras, int result) {
+ }
+}
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 8efc14f..cf14202 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -121,8 +121,8 @@
*/
public static final int FLAG_ONE_SHOT = 1<<30;
/**
- * Flag indicating that if the described PendingIntent already
- * exists, then simply return null instead of creating it.
+ * Flag indicating that if the described PendingIntent does not
+ * already exist, then simply return null instead of creating it.
* For use with {@link #getActivity}, {@link #getBroadcast}, and
* {@link #getService}.
*/
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 728f372..a67faa0 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -144,14 +144,16 @@
* Creates the top level Resources for applications with the given compatibility info.
*
* @param resDir the resource directory.
+ * @param overlayDirs the resource overlay directories.
+ * @param libDirs the shared library resource dirs this app references.
* @param compatInfo the compability info. Must not be null.
* @param token the application token for determining stack bounds.
*/
- public Resources getTopLevelResources(String resDir, String[] overlayDirs, int displayId,
- Configuration overrideConfiguration, CompatibilityInfo compatInfo, IBinder token) {
+ public Resources getTopLevelResources(String resDir, String[] overlayDirs, String[] libDirs,
+ int displayId, Configuration overrideConfiguration, CompatibilityInfo compatInfo,
+ IBinder token) {
final float scale = compatInfo.applicationScale;
- ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale,
- token);
+ ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale, token);
Resources r;
synchronized (this) {
// Resources is app scale dependent.
@@ -186,6 +188,15 @@
}
}
+ if (libDirs != null) {
+ for (String libDir : libDirs) {
+ if (assets.addAssetPath(libDir) == 0) {
+ Slog.w(TAG, "Asset path '" + libDir +
+ "' does not exist or contains no resources.");
+ }
+ }
+ }
+
//Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
DisplayMetrics dm = getDisplayMetricsLocked(displayId);
Configuration config;
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 66fc816..3074b49 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -52,6 +52,22 @@
static final String TAG = "DeviceAdminInfo";
/**
+ * A type of policy that this device admin can use: device owner meta-policy
+ * for an admin that is designated as owner of the device.
+ *
+ * @hide
+ */
+ public static final int USES_POLICY_DEVICE_OWNER = -2;
+
+ /**
+ * A type of policy that this device admin can use: profile owner meta-policy
+ * for admins that have been installed as owner of some user profile.
+ *
+ * @hide
+ */
+ public static final int USES_POLICY_PROFILE_OWNER = -1;
+
+ /**
* A type of policy that this device admin can use: limit the passwords
* that the user can select, via {@link DevicePolicyManager#setPasswordQuality}
* and {@link DevicePolicyManager#setPasswordMinimumLength}.
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 67c772b..3c31f8d 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -128,6 +128,13 @@
Handler mHandler = null;
+ Handler getHandler() {
+ if (mHandler == null) {
+ mHandler = new Handler(Looper.getMainLooper());
+ }
+ return mHandler;
+ }
+
class SharedPrefsSynchronizer implements Runnable {
public final CountDownLatch mLatch = new CountDownLatch(1);
@@ -140,12 +147,9 @@
// Syncing shared preferences deferred writes needs to happen on the main looper thread
private void waitForSharedPrefs() {
- if (mHandler == null) {
- mHandler = new Handler(Looper.getMainLooper());
- }
-
+ Handler h = getHandler();
final SharedPrefsSynchronizer s = new SharedPrefsSynchronizer();
- mHandler.postAtFrontOfQueue(s);
+ h.postAtFrontOfQueue(s);
try {
s.mLatch.await();
} catch (InterruptedException e) { /* ignored */ }
@@ -680,5 +684,23 @@
}
}
}
+
+ @Override
+ public void fail(String message) {
+ getHandler().post(new FailRunnable(message));
+ }
+ }
+
+ static class FailRunnable implements Runnable {
+ private String mMessage;
+
+ FailRunnable(String message) {
+ mMessage = message;
+ }
+
+ @Override
+ public void run() {
+ throw new IllegalStateException(mMessage);
+ }
}
}
diff --git a/core/java/android/app/backup/BackupDataOutput.java b/core/java/android/app/backup/BackupDataOutput.java
index 845784f..fc5fb3d 100644
--- a/core/java/android/app/backup/BackupDataOutput.java
+++ b/core/java/android/app/backup/BackupDataOutput.java
@@ -85,11 +85,6 @@
* @throws IOException if the write failed
*/
public int writeEntityHeader(String key, int dataSize) throws IOException {
- if (key != null && key.charAt(0) >= 0xff00) {
- if (Process.myUid() != Process.SYSTEM_UID) {
- throw new IllegalArgumentException("Invalid key " + key);
- }
- }
int result = writeEntityHeader_native(mBackupWriter, key, dataSize);
if (result >= 0) {
return result;
diff --git a/core/java/android/app/trust/ITrustListener.aidl b/core/java/android/app/trust/ITrustListener.aidl
new file mode 100644
index 0000000..4680043
--- /dev/null
+++ b/core/java/android/app/trust/ITrustListener.aidl
@@ -0,0 +1,26 @@
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package android.app.trust;
+
+/**
+ * Private API to be notified about trust changes.
+ *
+ * {@hide}
+ */
+oneway interface ITrustListener {
+ void onTrustChanged(boolean enabled, int userId);
+}
\ No newline at end of file
diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl
new file mode 100644
index 0000000..ad4ccbb
--- /dev/null
+++ b/core/java/android/app/trust/ITrustManager.aidl
@@ -0,0 +1,31 @@
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+package android.app.trust;
+
+import android.app.trust.ITrustListener;
+
+/**
+ * System private API to comunicate with trust service.
+ *
+ * {@hide}
+ */
+interface ITrustManager {
+ void reportUnlockAttempt(boolean successful, int userId);
+ void reportEnabledTrustAgentsChanged(int userId);
+ void registerTrustListener(in ITrustListener trustListener);
+ void unregisterTrustListener(in ITrustListener trustListener);
+}
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
new file mode 100644
index 0000000..e31c624
--- /dev/null
+++ b/core/java/android/app/trust/TrustManager.java
@@ -0,0 +1,134 @@
+/*
+ * 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.trust;
+
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Log;
+
+/**
+ * See {@link com.android.server.trust.TrustManagerService}
+ * @hide
+ */
+public class TrustManager {
+
+ private static final int MSG_TRUST_CHANGED = 1;
+
+ private static final String TAG = "TrustManager";
+
+ private final ITrustManager mService;
+ private final ArrayMap<TrustListener, ITrustListener> mTrustListeners;
+
+ public TrustManager(IBinder b) {
+ mService = ITrustManager.Stub.asInterface(b);
+ mTrustListeners = new ArrayMap<TrustListener, ITrustListener>();
+ }
+
+ /**
+ * Reports that user {@param userId} has tried to unlock the device.
+ *
+ * @param successful if true, the unlock attempt was successful.
+ *
+ * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+ */
+ public void reportUnlockAttempt(boolean successful, int userId) {
+ try {
+ mService.reportUnlockAttempt(successful, userId);
+ } catch (RemoteException e) {
+ onError(e);
+ }
+ }
+
+ /**
+ * Reports that the list of enabled trust agents changed for user {@param userId}.
+ *
+ * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+ */
+ public void reportEnabledTrustAgentsChanged(int userId) {
+ try {
+ mService.reportEnabledTrustAgentsChanged(userId);
+ } catch (RemoteException e) {
+ onError(e);
+ }
+ }
+
+ /**
+ * Registers a listener for trust events.
+ *
+ * Requires the {@link android.Manifest.permission#TRUST_LISTENER} permission.
+ */
+ public void registerTrustListener(final TrustListener trustListener) {
+ try {
+ ITrustListener.Stub iTrustListener = new ITrustListener.Stub() {
+ @Override
+ public void onTrustChanged(boolean enabled, int userId) throws RemoteException {
+ mHandler.obtainMessage(MSG_TRUST_CHANGED, (enabled ? 1 : 0), userId,
+ trustListener).sendToTarget();
+ }
+ };
+ mService.registerTrustListener(iTrustListener);
+ mTrustListeners.put(trustListener, iTrustListener);
+ } catch (RemoteException e) {
+ onError(e);
+ }
+ }
+
+ /**
+ * Unregisters a listener for trust events.
+ *
+ * Requires the {@link android.Manifest.permission#TRUST_LISTENER} permission.
+ */
+ public void unregisterTrustListener(final TrustListener trustListener) {
+ ITrustListener iTrustListener = mTrustListeners.remove(trustListener);
+ if (iTrustListener != null) {
+ try {
+ mService.unregisterTrustListener(iTrustListener);
+ } catch (RemoteException e) {
+ onError(e);
+ }
+ }
+ }
+
+ private void onError(Exception e) {
+ Log.e(TAG, "Error while calling TrustManagerService", e);
+ }
+
+ private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case MSG_TRUST_CHANGED:
+ ((TrustListener)msg.obj).onTrustChanged(msg.arg1 != 0, msg.arg2);
+ break;
+ }
+ }
+ };
+
+ public interface TrustListener {
+
+ /**
+ * Reports that the trust state has changed.
+ * @param enabled if true, the system believes the environment to be trusted.
+ * @param userId the user, for which the trust changed.
+ */
+ void onTrustChanged(boolean enabled, int userId);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index a4374b8..e79deec 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -567,7 +567,7 @@
}
/**
- * Stop BLE advertising.
+ * Stop BLE advertising. The callback has to be the same one used for start advertising.
*
* @param callback - {@link AdvertiseCallback}
* @return true if BLE advertising stops, false otherwise.
@@ -1986,7 +1986,13 @@
public void onAdvertiseStateChange(int advertiseState, int status) {
Log.d(TAG, "on advertise call back, state: " + advertiseState + " status: " + status);
if (advertiseState == STATE_ADVERTISE_STARTED) {
- mAdvertiseCallback.onAdvertiseStart(status);
+ if (status == ADVERTISE_CALLBACK_SUCCESS) {
+ mAdvertiseCallback.onAdvertiseStart(status);
+ } else {
+ // If status is unsuccessful and advertise state is started, it means stop
+ // advertising fails.
+ mAdvertiseCallback.onAdvertiseStop(status);
+ }
} else {
synchronized (this) {
if (status == ADVERTISE_CALLBACK_SUCCESS) {
@@ -2008,8 +2014,22 @@
}
}
}
- mAdvertiseCallback.onAdvertiseStop(status);
+ if (status == ADVERTISE_CALLBACK_SUCCESS) {
+ mAdvertiseCallback.onAdvertiseStop(status);
+ } else{
+ // If status is unsuccesful and advertise state is stopped, it means start
+ // advertising fails.
+ mAdvertiseCallback.onAdvertiseStart(status);
+ }
}
}
+
+ /**
+ * Callback reporting LE ATT MTU.
+ * @hide
+ */
+ public void onConfigureMTU(String address, int mtu, int status) {
+ // no op
+ }
}
}
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 39305b0..101b721 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -550,6 +550,23 @@
public void onAdvertiseStateChange(int state, int status) {
if (DBG) Log.d(TAG, "onAdvertiseStateChange() - state = "
+ state + " status=" + status);
+ }
+
+ /**
+ * Callback invoked when the MTU for a given connection changes
+ * @hide
+ */
+ public void onConfigureMTU(String address, int mtu, int status) {
+ if (DBG) Log.d(TAG, "onConfigureMTU() - Device=" + address +
+ " mtu=" + mtu + " status=" + status);
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ try {
+ mCallback.onConfigureMTU(BluetoothGatt.this, mtu, status);
+ } catch (Exception ex) {
+ Log.w(TAG, "Unhandled exception in callback", ex);
+ }
}
};
@@ -1137,6 +1154,36 @@
}
/**
+ * Configure the MTU used for a given connection.
+ *
+ * <p>When performing a write request operation (write without response),
+ * the data sent is truncated to the MTU size. This function may be used
+ * to request a larget MTU size to be able to send more data at once.
+ *
+ * <p>A {@link BluetoothGattCallback#onConfigureMTU} callback will indicate
+ * whether this operation was successful.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @return true, if the new MTU value has been requested successfully
+ * @hide
+ */
+ public boolean configureMTU(int mtu) {
+ if (DBG) Log.d(TAG, "configureMTU() - device: " + mDevice.getAddress()
+ + " mtu: " + mtu);
+ if (mService == null || mClientIf == 0) return false;
+
+ try {
+ mService.configureMTU(mClientIf, mDevice.getAddress(), mtu);
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
* Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
* with {@link BluetoothProfile#GATT} as argument
*
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
index 80ea4a6..5180259 100644
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattCallback.java
@@ -138,4 +138,19 @@
*/
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
}
+
+ /**
+ * Callback indicating the MTU for a given device connection has changed.
+ *
+ * This callback is triggered in response to the
+ * {@link BluetoothGatt#configureMTU} function, or in response to a connection
+ * event.
+ *
+ * @param gatt GATT client invoked {@link BluetoothGatt#configureMTU}
+ * @param mtu The new MTU size
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the MTU has been changed successfully
+ * @hide
+ */
+ public void onConfigureMTU(BluetoothGatt gatt, int mtu, int status) {
+ }
}
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 784cdcc..c6b5c3d 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -73,6 +73,7 @@
void beginReliableWrite(in int clientIf, in String address);
void endReliableWrite(in int clientIf, in String address, in boolean execute);
void readRemoteRssi(in int clientIf, in String address);
+ void configureMTU(in int clientIf, in String address, in int mtu);
void registerServer(in ParcelUuid appId, in IBluetoothGattServerCallback callback);
void unregisterServer(in int serverIf);
diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
index 7c69a06..a78c29b 100644
--- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
@@ -64,4 +64,5 @@
in byte[] value);
void onReadRemoteRssi(in String address, in int rssi, in int status);
oneway void onAdvertiseStateChange(in int advertiseState, in int status);
+ void onConfigureMTU(in String address, in int mtu, in int status);
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9f0c384..3fdaef2 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1974,6 +1974,7 @@
//@hide: NETWORK_STATS_SERVICE,
//@hide: NETWORK_POLICY_SERVICE,
WIFI_SERVICE,
+ WIFI_HOTSPOT_SERVICE,
WIFI_P2P_SERVICE,
NSD_SERVICE,
AUDIO_SERVICE,
@@ -2324,6 +2325,16 @@
/**
* Use with {@link #getSystemService} to retrieve a {@link
+ * android.net.wifi.hotspot.WifiHotspotManager} for handling management of
+ * Wi-Fi hotspot access.
+ *
+ * @see #getSystemService
+ * @see android.net.wifi.hotspot.WifiHotspotManager
+ */
+ public static final String WIFI_HOTSPOT_SERVICE = "wifihotspot";
+
+ /**
+ * Use with {@link #getSystemService} to retrieve a {@link
* android.net.wifi.p2p.WifiP2pManager} for handling management of
* Wi-Fi peer-to-peer connections.
*
@@ -2584,6 +2595,14 @@
public static final String CONSUMER_IR_SERVICE = "consumer_ir";
/**
+ * {@link android.app.trust.TrustManager} for managing trust agents.
+ * @see #getSystemService
+ * @see android.app.trust.TrustManager
+ * @hide
+ */
+ public static final String TRUST_SERVICE = "trust";
+
+ /**
* 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/Intent.java b/core/java/android/content/Intent.java
index 0175d62..d189a34 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2173,6 +2173,11 @@
/**
* Broadcast Action: Wired Headset plugged in or unplugged.
*
+ * You <em>cannot</em> receive this through components declared
+ * in manifests, only by explicitly registering for it with
+ * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
+ * Context.registerReceiver()}.
+ *
* <p>The intent will have the following extra values:
* <ul>
* <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
@@ -2879,6 +2884,14 @@
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
public static final String CATEGORY_CAR_MODE = "android.intent.category.CAR_MODE";
+ /**
+ * An activity that provides a user interface for adjusting notification preferences for its
+ * containing application. Optional but recommended for apps that post
+ * {@link android.app.Notification Notifications}.
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_NOTIFICATION_PREFERENCES = "android.intent.category.NOTIFICATION_PREFERENCES";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Application launch intent categories (see addCategory()).
diff --git a/core/java/android/content/pm/IPackageInstallObserver2.aidl b/core/java/android/content/pm/IPackageInstallObserver2.aidl
new file mode 100644
index 0000000..2602ab5
--- /dev/null
+++ b/core/java/android/content/pm/IPackageInstallObserver2.aidl
@@ -0,0 +1,45 @@
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.content.pm;
+
+import android.os.Bundle;
+
+/**
+ * API for installation callbacks from the Package Manager. In certain result cases
+ * additional information will be provided.
+ * @hide
+ */
+oneway interface IPackageInstallObserver2 {
+ /**
+ * The install operation has completed. {@code returnCode} holds a numeric code
+ * indicating success or failure. In certain cases the {@code extras} Bundle will
+ * contain additional details:
+ *
+ * <p><table>
+ * <tr>
+ * <td>INSTALL_FAILED_DUPLICATE_PERMISSION</td>
+ * <td>Two strings are provided in the extras bundle: EXTRA_EXISTING_PERMISSION
+ * is the name of the permission that the app is attempting to define, and
+ * EXTRA_EXISTING_PACKAGE is the package name of the app which has already
+ * defined the permission.</td>
+ * </tr>
+ * </table>
+ */
+ void packageInstalled(in String packageName, in Bundle extras, int returnCode);
+}
+
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index c9fb530..ae0899f 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -25,6 +25,7 @@
import android.content.pm.ContainerEncryptionParams;
import android.content.pm.FeatureInfo;
import android.content.pm.IPackageInstallObserver;
+import android.content.pm.IPackageInstallObserver2;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageMoveObserver;
@@ -406,6 +407,21 @@
in VerificationParams verificationParams,
in ContainerEncryptionParams encryptionParams);
+ /** Expanded observer versions */
+ void installPackageEtc(in Uri packageURI, IPackageInstallObserver observer,
+ IPackageInstallObserver2 observer2, int flags, in String installerPackageName);
+
+ void installPackageWithVerificationEtc(in Uri packageURI,
+ in IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
+ int flags, in String installerPackageName, in Uri verificationURI,
+ in ManifestDigest manifestDigest, in ContainerEncryptionParams encryptionParams);
+
+ void installPackageWithVerificationAndEncryptionEtc(in Uri packageURI,
+ in IPackageInstallObserver observer, in IPackageInstallObserver2 observer2,
+ int flags, in String installerPackageName,
+ in VerificationParams verificationParams,
+ in ContainerEncryptionParams encryptionParams);
+
int installExistingPackageAsUser(String packageName, int userId);
void verifyPendingInstall(int id, int verificationCode);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e86833b..ceb7764 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.app.PackageInstallObserver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -683,6 +684,20 @@
public static final int INSTALL_FAILED_USER_RESTRICTED = -111;
/**
+ * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by
+ * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
+ * if the system failed to install the package because it is attempting to define a
+ * permission that is already defined by some existing package.
+ *
+ * <p>The package name of the app which has already defined the permission is passed to
+ * a {@link IPackageInstallObserver2}, if any, as the {@link #EXTRA_EXISTING_PACKAGE}
+ * string extra; and the name of the permission being redefined is passed in the
+ * {@link #EXTRA_EXISTING_PERMISSION} string extra.
+ * @hide
+ */
+ public static final int INSTALL_FAILED_DUPLICATE_PERMISSION = -112;
+
+ /**
* Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the
* package's data directory.
*
@@ -1390,6 +1405,24 @@
= "android.content.pm.extra.PERMISSION_LIST";
/**
+ * String extra for {@link IPackageInstallObserver2} in the 'extras' Bundle in case of
+ * {@link #INSTALL_FAILED_DUPLICATE_PERMISSION}. This extra names the package which provides
+ * the existing definition for the permission.
+ * @hide
+ */
+ public static final String EXTRA_FAILURE_EXISTING_PACKAGE
+ = "android.content.pm.extra.FAILURE_EXISTING_PACKAGE";
+
+ /**
+ * String extra for {@link IPackageInstallObserver2} in the 'extras' Bundle in case of
+ * {@link #INSTALL_FAILED_DUPLICATE_PERMISSION}. This extra names the permission that is
+ * being redundantly defined by the package being installed.
+ * @hide
+ */
+ public static final String EXTRA_FAILURE_EXISTING_PERMISSION
+ = "android.content.pm.extra.FAILURE_EXISTING_PERMISSION";
+
+ /**
* Retrieve overall information about an application package that is
* installed on the system.
* <p>
@@ -2752,11 +2785,14 @@
* 'content:' URI.
* @param observer An observer callback to get notified when the package installation is
* complete. {@link IPackageInstallObserver#packageInstalled(String, int)} will be
- * called when that happens. observer may be null to indicate that no callback is desired.
+ * called when that happens. This parameter must not be null.
* @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
* {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
* @param installerPackageName Optional package name of the application that is performing the
* installation. This identifies which market the package came from.
+ * @deprecated Use {@link #installPackage(Uri, IPackageInstallObserver2, int, String)}
+ * instead. This method will continue to be supported but the older observer interface
+ * will not get additional failure details.
*/
public abstract void installPackage(
Uri packageURI, IPackageInstallObserver observer, int flags,
@@ -2772,11 +2808,9 @@
* @param observer An observer callback to get notified when the package
* installation is complete.
* {@link IPackageInstallObserver#packageInstalled(String, int)}
- * will be called when that happens. observer may be null to
- * indicate that no callback is desired.
+ * will be called when that happens. This parameter must not be null.
* @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
- * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}
- * .
+ * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
* @param installerPackageName Optional package name of the application that
* is performing the installation. This identifies which market
* the package came from.
@@ -2789,6 +2823,10 @@
* these parameters describing the encryption and authentication
* used. May be {@code null}.
* @hide
+ * @deprecated Use {@link #installPackageWithVerification(Uri, IPackageInstallObserver2,
+ * int, String, Uri, ManifestDigest, ContainerEncryptionParams)} instead. This method will
+ * continue to be supported but the older observer interface will not get additional failure
+ * details.
*/
public abstract void installPackageWithVerification(Uri packageURI,
IPackageInstallObserver observer, int flags, String installerPackageName,
@@ -2805,11 +2843,99 @@
* @param observer An observer callback to get notified when the package
* installation is complete.
* {@link IPackageInstallObserver#packageInstalled(String, int)}
- * will be called when that happens. observer may be null to
- * indicate that no callback is desired.
+ * will be called when that happens. This parameter must not be null.
* @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
- * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}
- * .
+ * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
+ * @param installerPackageName Optional package name of the application that
+ * is performing the installation. This identifies which market
+ * the package came from.
+ * @param verificationParams an object that holds signal information to
+ * assist verification. May be {@code null}.
+ * @param encryptionParams if the package to be installed is encrypted,
+ * these parameters describing the encryption and authentication
+ * used. May be {@code null}.
+ *
+ * @hide
+ * @deprecated Use {@link #installPackageWithVerificationAndEncryption(Uri,
+ * IPackageInstallObserver2, int, String, VerificationParams,
+ * ContainerEncryptionParams)} instead. This method will continue to be
+ * supported but the older observer interface will not get additional failure details.
+ */
+ @Deprecated
+ public abstract void installPackageWithVerificationAndEncryption(Uri packageURI,
+ IPackageInstallObserver observer, int flags, String installerPackageName,
+ VerificationParams verificationParams,
+ ContainerEncryptionParams encryptionParams);
+
+ // Package-install variants that take the new, expanded form of observer interface.
+ // Note that these *also* take the original observer type and will redundantly
+ // report the same information to that observer if supplied; but it is not required.
+
+ /**
+ * @hide
+ *
+ * Install a package. Since this may take a little while, the result will
+ * be posted back to the given observer. An installation will fail if the calling context
+ * lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the
+ * package named in the package file's manifest is already installed, or if there's no space
+ * available on the device.
+ *
+ * @param packageURI The location of the package file to install. This can be a 'file:' or a
+ * 'content:' URI.
+ * @param observer An observer callback to get notified when the package installation is
+ * complete. {@link PackageInstallObserver#packageInstalled(String, Bundle, int)} will be
+ * called when that happens. This parameter must not be null.
+ * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
+ * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
+ * @param installerPackageName Optional package name of the application that is performing the
+ * installation. This identifies which market the package came from.
+ */
+ public abstract void installPackage(
+ Uri packageURI, PackageInstallObserver observer,
+ int flags, String installerPackageName);
+
+ /**
+ * Similar to
+ * {@link #installPackage(Uri, IPackageInstallObserver, int, String)} but
+ * with an extra verification file provided.
+ *
+ * @param packageURI The location of the package file to install. This can
+ * be a 'file:' or a 'content:' URI.
+ * @param observer An observer callback to get notified when the package installation is
+ * complete. {@link PackageInstallObserver#packageInstalled(String, Bundle, int)} will be
+ * called when that happens. This parameter must not be null.
+ * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
+ * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
+ * @param installerPackageName Optional package name of the application that
+ * is performing the installation. This identifies which market
+ * the package came from.
+ * @param verificationURI The location of the supplementary verification
+ * file. This can be a 'file:' or a 'content:' URI. May be
+ * {@code null}.
+ * @param manifestDigest an object that holds the digest of the package
+ * which can be used to verify ownership. May be {@code null}.
+ * @param encryptionParams if the package to be installed is encrypted,
+ * these parameters describing the encryption and authentication
+ * used. May be {@code null}.
+ * @hide
+ */
+ public abstract void installPackageWithVerification(Uri packageURI,
+ PackageInstallObserver observer, int flags, String installerPackageName,
+ Uri verificationURI, ManifestDigest manifestDigest,
+ ContainerEncryptionParams encryptionParams);
+
+ /**
+ * Similar to
+ * {@link #installPackage(Uri, IPackageInstallObserver, int, String)} but
+ * with an extra verification information provided.
+ *
+ * @param packageURI The location of the package file to install. This can
+ * be a 'file:' or a 'content:' URI.
+ * @param observer An observer callback to get notified when the package installation is
+ * complete. {@link PackageInstallObserver#packageInstalled(String, Bundle, int)} will be
+ * called when that happens. This parameter must not be null.
+ * @param flags - possible values: {@link #INSTALL_FORWARD_LOCK},
+ * {@link #INSTALL_REPLACE_EXISTING}, {@link #INSTALL_ALLOW_TEST}.
* @param installerPackageName Optional package name of the application that
* is performing the installation. This identifies which market
* the package came from.
@@ -2822,9 +2948,8 @@
* @hide
*/
public abstract void installPackageWithVerificationAndEncryption(Uri packageURI,
- IPackageInstallObserver observer, int flags, String installerPackageName,
- VerificationParams verificationParams,
- ContainerEncryptionParams encryptionParams);
+ PackageInstallObserver observer, int flags, String installerPackageName,
+ VerificationParams verificationParams, ContainerEncryptionParams encryptionParams);
/**
* If there is already an application with the given package name installed
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index cf44ad8..a89c507 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1010,13 +1010,14 @@
pkg.mSharedUserLabel = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
}
- sa.recycle();
pkg.installLocation = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_installLocation,
PARSE_DEFAULT_INSTALL_LOCATION);
pkg.applicationInfo.installLocation = pkg.installLocation;
+ sa.recycle();
+
/* Set the global "forward lock" flag */
if ((flags & PARSE_FORWARD_LOCK) != 0) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;
@@ -1105,7 +1106,6 @@
if (!parseUsesPermission(pkg, res, parser, attrs, outError)) {
return null;
}
-
} else if (tagName.equals("uses-configuration")) {
ConfigurationInfo cPref = new ConfigurationInfo();
sa = res.obtainAttributes(attrs,
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 6f1d4f8..f53aa4c 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -71,7 +71,7 @@
public static final int FLAG_MANAGED_PROFILE = 0x00000020;
- public static final int NO_RELATED_GROUP_ID = -1;
+ public static final int NO_PROFILE_GROUP_ID = -1;
public int id;
public int serialNumber;
@@ -80,7 +80,7 @@
public int flags;
public long creationTime;
public long lastLoggedInTime;
- public int relatedGroupId;
+ public int profileGroupId;
/** User is only partially created. */
public boolean partial;
@@ -94,7 +94,7 @@
this.name = name;
this.flags = flags;
this.iconPath = iconPath;
- this.relatedGroupId = NO_RELATED_GROUP_ID;
+ this.profileGroupId = NO_PROFILE_GROUP_ID;
}
public boolean isPrimary() {
@@ -137,7 +137,7 @@
creationTime = orig.creationTime;
lastLoggedInTime = orig.lastLoggedInTime;
partial = orig.partial;
- relatedGroupId = orig.relatedGroupId;
+ profileGroupId = orig.profileGroupId;
}
public UserHandle getUserHandle() {
@@ -162,7 +162,7 @@
dest.writeLong(creationTime);
dest.writeLong(lastLoggedInTime);
dest.writeInt(partial ? 1 : 0);
- dest.writeInt(relatedGroupId);
+ dest.writeInt(profileGroupId);
}
public static final Parcelable.Creator<UserInfo> CREATOR
@@ -184,6 +184,6 @@
creationTime = source.readLong();
lastLoggedInTime = source.readLong();
partial = source.readInt() != 0;
- relatedGroupId = source.readInt();
+ profileGroupId = source.readInt();
}
}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 2f8dd53..0c04401 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -18,6 +18,7 @@
import android.os.ParcelFileDescriptor;
import android.util.Log;
+import android.util.SparseArray;
import android.util.TypedValue;
import java.io.FileNotFoundException;
@@ -266,11 +267,9 @@
}
}
- /*package*/ final CharSequence getPooledString(int block, int id) {
- //System.out.println("Get pooled: block=" + block
- // + ", id=#" + Integer.toHexString(id)
- // + ", blocks=" + mStringBlocks);
- return mStringBlocks[block-1].get(id);
+ /*package*/ final CharSequence getPooledStringForCookie(int cookie, int id) {
+ // Cookies map to string blocks starting at 1.
+ return mStringBlocks[cookie - 1].get(id);
}
/**
@@ -740,6 +739,11 @@
/**
* {@hide}
*/
+ public native final SparseArray<String> getAssignedPackageIdentifiers();
+
+ /**
+ * {@hide}
+ */
public native static final int getGlobalAssetCount();
/**
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 419abf2..5674154 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -19,6 +19,7 @@
import android.graphics.Color;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -181,10 +182,9 @@
final int innerDepth = parser.getDepth()+1;
int depth;
- int listAllocated = 20;
+ int[][] stateSpecList = ArrayUtils.newUnpaddedArray(int[].class, 20);
+ int[] colorList = new int[stateSpecList.length];
int listSize = 0;
- int[] colorList = new int[listAllocated];
- int[][] stateSpecList = new int[listAllocated][];
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
&& ((depth=parser.getDepth()) >= innerDepth
@@ -248,21 +248,8 @@
mDefaultColor = color;
}
- if (listSize + 1 >= listAllocated) {
- listAllocated = ArrayUtils.idealIntArraySize(listSize + 1);
-
- int[] ncolor = new int[listAllocated];
- System.arraycopy(colorList, 0, ncolor, 0, listSize);
-
- int[][] nstate = new int[listAllocated][];
- System.arraycopy(stateSpecList, 0, nstate, 0, listSize);
-
- colorList = ncolor;
- stateSpecList = nstate;
- }
-
- colorList[listSize] = color;
- stateSpecList[listSize] = stateSpec;
+ colorList = GrowingArrayUtils.append(colorList, listSize, color);
+ stateSpecList = GrowingArrayUtils.append(stateSpecList, listSize, stateSpec);
listSize++;
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index affc784..d6eafc6 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -114,7 +114,6 @@
private boolean mPreloading;
private TypedArray mCachedStyledAttributes = null;
- private RuntimeException mLastRetrievedAttrs = null;
private int mLastCachedXmlBlockIndex = -1;
private final int[] mCachedXmlBlockIds = { 0, 0, 0, 0 };
@@ -136,17 +135,31 @@
sPreloadedDrawables[1] = new LongSparseArray<ConstantState>();
}
- /** @hide */
+ /**
+ * Returns the most appropriate default theme for the specified target SDK version.
+ * <ul>
+ * <li>Below API 11: Gingerbread
+ * <li>APIs 11 thru 14: Holo
+ * <li>APIs 14 thru XX: Device default dark
+ * <li>API XX and above: Device default light with dark action bar
+ * </ul>
+ *
+ * @param curTheme The current theme, or 0 if not specified.
+ * @param targetSdkVersion The target SDK version.
+ * @return A theme resource identifier
+ * @hide
+ */
public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
return selectSystemTheme(curTheme, targetSdkVersion,
com.android.internal.R.style.Theme,
com.android.internal.R.style.Theme_Holo,
- com.android.internal.R.style.Theme_DeviceDefault);
+ com.android.internal.R.style.Theme_DeviceDefault,
+ com.android.internal.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}
-
+
/** @hide */
- public static int selectSystemTheme(int curTheme, int targetSdkVersion,
- int orig, int holo, int deviceDefault) {
+ public static int selectSystemTheme(int curTheme, int targetSdkVersion, int orig, int holo,
+ int dark, int deviceDefault) {
if (curTheme != 0) {
return curTheme;
}
@@ -156,9 +169,12 @@
if (targetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
return holo;
}
+ if (targetSdkVersion < Build.VERSION_CODES.CUR_DEVELOPMENT) {
+ return dark;
+ }
return deviceDefault;
}
-
+
/**
* This exception is thrown by the resource APIs when a requested resource
* can not be found.
@@ -1253,12 +1269,9 @@
public void applyStyle(int resid, boolean force) {
AssetManager.applyThemeStyle(mTheme, resid, force);
- if (!mHasStyle) {
- mHasStyle = true;
- mThemeResId = resid;
- } else if (resid != mThemeResId) {
- mThemeResId = 0;
- }
+ // TODO: In very rare cases, we may end up with a hybrid theme
+ // that can't map to a single theme ID.
+ mThemeResId = resid;
}
/**
@@ -1273,7 +1286,6 @@
public void setTo(Theme other) {
AssetManager.copyTheme(mTheme, other.mTheme);
- mHasStyle = other.mHasStyle;
mThemeResId = other.mThemeResId;
}
@@ -1562,10 +1574,6 @@
mAssets.releaseTheme(mTheme);
}
- /*package*/ boolean canCacheDrawables() {
- return mHasStyle && mThemeResId != 0;
- }
-
/*package*/ Theme() {
mAssets = Resources.this.mAssets;
mTheme = mAssets.createTheme();
@@ -1575,12 +1583,8 @@
private final AssetManager mAssets;
private final long mTheme;
- /**
- * Resource identifier for the theme. If multiple styles have been
- * applied to this theme, this value will be 0 (invalid).
- */
+ /** Resource identifier for the theme. */
private int mThemeResId = 0;
- private boolean mHasStyle = false;
}
/**
@@ -2260,11 +2264,6 @@
return;
}
- // Abort if the drawable is themed, but the theme cannot be cached.
- if (dr.canApplyTheme() && theme != null && !theme.canCacheDrawables()) {
- return;
- }
-
if (mPreloading) {
// Preloaded drawables never have a theme, but may be themeable.
final int changingConfigs = cs.getChangingConfigurations();
@@ -2289,11 +2288,7 @@
} else {
synchronized (mAccessLock) {
final LongSparseArray<WeakReference<ConstantState>> themedCache;
- if (!dr.canApplyTheme()) {
- themedCache = caches.getUnthemed(true);
- } else {
- themedCache = caches.getOrCreate(theme == null ? 0 : theme.mThemeResId);
- }
+ themedCache = caches.getOrCreate(theme == null ? 0 : theme.mThemeResId);
themedCache.put(key, new WeakReference<ConstantState>(cs));
}
}
@@ -2354,21 +2349,6 @@
private Drawable getCachedDrawable(ThemedCaches<ConstantState> caches, long key, Theme theme) {
synchronized (mAccessLock) {
- // First, check for a matching unthemed drawable.
- final LongSparseArray<WeakReference<ConstantState>> unthemed = caches.getUnthemed(false);
- if (unthemed != null) {
- final Drawable unthemedDrawable = getCachedDrawableLocked(unthemed, key);
- if (unthemedDrawable != null) {
- return unthemedDrawable;
- }
- }
-
- final boolean themeCannotCache = theme != null && !theme.canCacheDrawables();
- if (themeCannotCache) {
- return null;
- }
-
- // Next, check for a matching themed drawable.
final int themeKey = theme != null ? theme.mThemeResId : 0;
final LongSparseArray<WeakReference<ConstantState>> themedCache = caches.get(themeKey);
if (themedCache != null) {
@@ -2606,18 +2586,6 @@
}
static class ThemedCaches<T> extends SparseArray<LongSparseArray<WeakReference<T>>> {
- private LongSparseArray<WeakReference<T>> mUnthemed = null;
-
- /**
- * Returns the cache of drawables with no themeable attributes.
- */
- public LongSparseArray<WeakReference<T>> getUnthemed(boolean autoCreate) {
- if (mUnthemed == null && autoCreate) {
- mUnthemed = new LongSparseArray<WeakReference<T>>(1);
- }
- return mUnthemed;
- }
-
/**
* Returns the cache of drawables styled for the specified theme.
* <p>
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index baf887e..15337ce 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -32,7 +32,7 @@
* {@link Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)}
* or {@link Resources#obtainAttributes}. Be
* sure to call {@link #recycle} when done with them.
- *
+ *
* The indices used to retrieve values from this structure correspond to
* the positions of the attributes given to obtainStyledAttributes.
*/
@@ -46,6 +46,7 @@
attrs.mResources = res;
attrs.mMetrics = res.getDisplayMetrics();
attrs.mAssets = res.getAssets();
+ attrs.mRecycled = false;
final int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;
if (attrs.mData.length >= fullLen) {
@@ -65,6 +66,8 @@
private Resources mResources;
private DisplayMetrics mMetrics;
private AssetManager mAssets;
+ private boolean mRecycled;
+
/*package*/ XmlBlock.Parser mXml;
/*package*/ Resources.Theme mTheme;
/*package*/ int[] mData;
@@ -76,45 +79,65 @@
* Return the number of values in this array.
*/
public int length() {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
return mLength;
}
-
+
/**
* Return the number of indices in the array that actually have data.
*/
public int getIndexCount() {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
return mIndices[0];
}
-
+
/**
* Return an index in the array that has data.
- *
+ *
* @param at The index you would like to returned, ranging from 0 to
* {@link #getIndexCount()}.
- *
+ *
* @return The index at the given offset, which can be used with
* {@link #getValue} and related APIs.
*/
public int getIndex(int at) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
return mIndices[1+at];
}
-
+
/**
* Return the Resources object this array was loaded from.
*/
public Resources getResources() {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
return mResources;
}
-
+
/**
* Retrieve the styled string value for the attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
- *
- * @return CharSequence holding string data. May be styled. Returns
+ *
+ * @return CharSequence holding string data. May be styled. Returns
* null if the attribute is not defined.
*/
public CharSequence getText(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -136,13 +159,17 @@
/**
* Retrieve the string value for the attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
- *
+ *
* @return String holding string data. Any styling information is
* removed. Returns null if the attribute is not defined.
*/
public String getString(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -170,14 +197,18 @@
* attributes, or conversions from other types. As such, this method
* will only return strings for TypedArray objects that come from
* attributes in an XML file.
- *
+ *
* @param index Index of attribute to retrieve.
- *
+ *
* @return String holding string data. Any styling information is
* removed. Returns null if the attribute is not defined or is not
* an immediate string value.
*/
public String getNonResourceString(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -190,12 +221,12 @@
}
return null;
}
-
+
/**
* @hide
* Retrieve the string value for the attribute at <var>index</var> that is
* not allowed to change with the given configurations.
- *
+ *
* @param index Index of attribute to retrieve.
* @param allowedChangingConfigs Bit mask of configurations from
* {@link Configuration}.NATIVE_CONFIG_* that are allowed to change.
@@ -204,6 +235,10 @@
* removed. Returns null if the attribute is not defined.
*/
public String getNonConfigurationString(int index, int allowedChangingConfigs) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -229,13 +264,17 @@
/**
* Retrieve the boolean value for the attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined.
- *
+ *
* @return Attribute boolean value, or defValue if not defined.
*/
public boolean getBoolean(int index, boolean defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -259,13 +298,17 @@
/**
* Retrieve the integer value for the attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined.
- *
+ *
* @return Attribute int value, or defValue if not defined.
*/
public int getInt(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -289,12 +332,16 @@
/**
* Retrieve the float value for the attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
- *
+ *
* @return Attribute float value, or defValue if not defined..
*/
public float getFloat(int index, float defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -319,20 +366,24 @@
+ Integer.toHexString(type));
return defValue;
}
-
+
/**
* Retrieve the color value for the attribute at <var>index</var>. If
* the attribute references a color resource holding a complex
* {@link android.content.res.ColorStateList}, then the default color from
* the set is returned.
- *
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined or
* not a resource.
- *
+ *
* @return Attribute color value, or defValue if not defined.
*/
public int getColor(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -359,12 +410,16 @@
* Retrieve the ColorStateList for the attribute at <var>index</var>.
* The value may be either a single solid color or a reference to
* a color or complex {@link android.content.res.ColorStateList} description.
- *
+ *
* @param index Index of attribute to retrieve.
- *
+ *
* @return ColorStateList for the attribute, or null if not defined.
*/
public ColorStateList getColorStateList(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
final TypedValue value = mValue;
if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
return mResources.loadColorStateList(value, value.resourceId);
@@ -374,14 +429,18 @@
/**
* Retrieve the integer value for the attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined or
* not a resource.
- *
+ *
* @return Attribute integer value, or defValue if not defined.
*/
public int getInteger(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -397,22 +456,26 @@
}
/**
- * Retrieve a dimensional unit attribute at <var>index</var>. Unit
- * conversions are based on the current {@link DisplayMetrics}
- * associated with the resources this {@link TypedArray} object
- * came from.
- *
+ * Retrieve a dimensional unit attribute at <var>index</var>. Unit
+ * conversions are based on the current {@link DisplayMetrics}
+ * associated with the resources this {@link TypedArray} object
+ * came from.
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined or
* not a resource.
- *
- * @return Attribute dimension value multiplied by the appropriate
+ *
+ * @return Attribute dimension value multiplied by the appropriate
* metric, or defValue if not defined.
- *
+ *
* @see #getDimensionPixelOffset
* @see #getDimensionPixelSize
*/
public float getDimension(int index, float defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -433,18 +496,22 @@
* {@link #getDimension}, except the returned value is converted to
* integer pixels for you. An offset conversion involves simply
* truncating the base value to an integer.
- *
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined or
* not a resource.
- *
- * @return Attribute dimension value multiplied by the appropriate
+ *
+ * @return Attribute dimension value multiplied by the appropriate
* metric and truncated to integer pixels, or defValue if not defined.
- *
+ *
* @see #getDimension
* @see #getDimensionPixelSize
*/
public int getDimensionPixelOffset(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -466,18 +533,22 @@
* integer pixels for use as a size. A size conversion involves
* rounding the base value, and ensuring that a non-zero base value
* is at least one pixel in size.
- *
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined or
* not a resource.
- *
- * @return Attribute dimension value multiplied by the appropriate
+ *
+ * @return Attribute dimension value multiplied by the appropriate
* metric and truncated to integer pixels, or defValue if not defined.
- *
+ *
* @see #getDimension
* @see #getDimensionPixelOffset
*/
public int getDimensionPixelSize(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -497,14 +568,18 @@
* {@link android.view.ViewGroup}'s layout_width and layout_height
* attributes. This is only here for performance reasons; applications
* should use {@link #getDimensionPixelSize}.
- *
+ *
* @param index Index of the attribute to retrieve.
* @param name Textual name of attribute for error reporting.
- *
- * @return Attribute dimension value multiplied by the appropriate
+ *
+ * @return Attribute dimension value multiplied by the appropriate
* metric and truncated to integer pixels.
*/
public int getLayoutDimension(int index, String name) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -519,21 +594,25 @@
throw new RuntimeException(getPositionDescription()
+ ": You must supply a " + name + " attribute.");
}
-
+
/**
* Special version of {@link #getDimensionPixelSize} for retrieving
* {@link android.view.ViewGroup}'s layout_width and layout_height
* attributes. This is only here for performance reasons; applications
* should use {@link #getDimensionPixelSize}.
- *
+ *
* @param index Index of the attribute to retrieve.
* @param defValue The default value to return if this attribute is not
* default or contains the wrong type of data.
- *
- * @return Attribute dimension value multiplied by the appropriate
+ *
+ * @return Attribute dimension value multiplied by the appropriate
* metric and truncated to integer pixels.
*/
public int getLayoutDimension(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -550,20 +629,24 @@
/**
* Retrieve a fractional unit attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- * @param base The base value of this fraction. In other words, a
+ *
+ * @param index Index of attribute to retrieve.
+ * @param base The base value of this fraction. In other words, a
* standard fraction is multiplied by this value.
- * @param pbase The parent base value of this fraction. In other
+ * @param pbase The parent base value of this fraction. In other
* words, a parent fraction (nn%p) is multiplied by this
* value.
* @param defValue Value to return if the attribute is not defined or
* not a resource.
- *
- * @return Attribute fractional value multiplied by the appropriate
- * base value, or defValue if not defined.
+ *
+ * @return Attribute fractional value multiplied by the appropriate
+ * base value, or defValue if not defined.
*/
public float getFraction(int index, int base, int pbase, float defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
@@ -580,19 +663,23 @@
/**
* Retrieve the resource identifier for the attribute at
- * <var>index</var>. Note that attribute resource as resolved when
- * the overall {@link TypedArray} object is retrieved. As a
- * result, this function will return the resource identifier of the
- * final resource value that was found, <em>not</em> necessarily the
- * original resource that was specified by the attribute.
- *
+ * <var>index</var>. Note that attribute resource as resolved when
+ * the overall {@link TypedArray} object is retrieved. As a
+ * result, this function will return the resource identifier of the
+ * final resource value that was found, <em>not</em> necessarily the
+ * original resource that was specified by the attribute.
+ *
* @param index Index of attribute to retrieve.
* @param defValue Value to return if the attribute is not defined or
* not a resource.
- *
+ *
* @return Attribute resource identifier, or defValue if not defined.
*/
public int getResourceId(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
if (data[index+AssetManager.STYLE_TYPE] != TypedValue.TYPE_NULL) {
@@ -615,6 +702,10 @@
* @hide
*/
public int getThemeAttributeId(int index, int defValue) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
if (data[index + AssetManager.STYLE_TYPE] == TypedValue.TYPE_ATTRIBUTE) {
@@ -628,12 +719,16 @@
* gets the resource ID of the selected attribute, and uses
* {@link Resources#getDrawable Resources.getDrawable} of the owning
* Resources object to retrieve its Drawable.
- *
+ *
* @param index Index of attribute to retrieve.
- *
+ *
* @return Drawable for the attribute, or null if not defined.
*/
public Drawable getDrawable(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
final TypedValue value = mValue;
if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
if (false) {
@@ -655,12 +750,16 @@
* This gets the resource ID of the selected attribute, and uses
* {@link Resources#getTextArray Resources.getTextArray} of the owning
* Resources object to retrieve its String[].
- *
+ *
* @param index Index of attribute to retrieve.
- *
+ *
* @return CharSequence[] for the attribute, or null if not defined.
*/
public CharSequence[] getTextArray(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
final TypedValue value = mValue;
if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
if (false) {
@@ -679,36 +778,19 @@
/**
* Retrieve the raw TypedValue for the attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
* @param outValue TypedValue object in which to place the attribute's
* data.
- *
- * @return Returns true if the value was retrieved, else false.
+ *
+ * @return Returns true if the value was retrieved, else false.
*/
public boolean getValue(int index, TypedValue outValue) {
- return getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, outValue);
- }
-
- /**
- * Determines whether this TypedArray contains an attribute of the specified
- * type.
- *
- * @param type Type of data, e.g. {@link TypedValue#TYPE_ATTRIBUTE}
- * @return True if the TypedArray contains an attribute of the specified
- * type.
- * @hide
- */
- public boolean hasType(int type) {
- final int[] data = mData;
- final int N = getIndexCount();
- for (int i = 0; i < N; i++) {
- final int index = getIndex(i) * AssetManager.STYLE_NUM_ENTRIES;
- if (data[index + AssetManager.STYLE_TYPE] == type) {
- return true;
- }
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
}
- return false;
+
+ return getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, outValue);
}
/**
@@ -718,36 +800,48 @@
* @return Attribute type.
*/
public int getType(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
return mData[index + AssetManager.STYLE_TYPE];
}
/**
* Determines whether there is an attribute at <var>index</var>.
- *
+ *
* @param index Index of attribute to retrieve.
- *
+ *
* @return True if the attribute has a value, false otherwise.
*/
public boolean hasValue(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE];
return type != TypedValue.TYPE_NULL;
}
-
+
/**
- * Retrieve the raw TypedValue for the attribute at <var>index</var>
- * and return a temporary object holding its data. This object is only
- * valid until the next call on to {@link TypedArray}.
- *
+ * Retrieve the raw TypedValue for the attribute at <var>index</var>
+ * and return a temporary object holding its data. This object is only
+ * valid until the next call on to {@link TypedArray}.
+ *
* @param index Index of attribute to retrieve.
- *
- * @return Returns a TypedValue object if the attribute is defined,
+ *
+ * @return Returns a TypedValue object if the attribute is defined,
* containing its data; otherwise returns null. (You will not
* receive a TypedValue whose type is TYPE_NULL.)
*/
public TypedValue peekValue(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
final TypedValue value = mValue;
if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
return value;
@@ -759,13 +853,23 @@
* Returns a message about the parser state suitable for printing error messages.
*/
public String getPositionDescription() {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
return mXml != null ? mXml.getPositionDescription() : "<internal>";
}
/**
- * Give back a previously retrieved array, for later re-use.
+ * Recycle the TypedArray, to be re-used by a later caller. After calling
+ * this function you must not ever touch the typed array again.
*/
public void recycle() {
+ if (mRecycled) {
+ throw new RuntimeException(toString() + " recycled twice!");
+ }
+
+ mRecycled = true;
mResources = null;
mMetrics = null;
mAssets = null;
@@ -791,12 +895,15 @@
* @hide
*/
public int[] extractThemeAttrs() {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
int[] attrs = null;
- final int N = getIndexCount();
+ final int N = length();
for (int i = 0; i < N; i++) {
- final int index = getIndex(i);
- final int attrId = getThemeAttributeId(index, 0);
+ final int attrId = getThemeAttributeId(i, 0);
if (attrId != 0) {
if (attrs == null) {
attrs = new int[N];
@@ -834,7 +941,7 @@
}
return null;
}
- return mAssets.getPooledString(cookie, data[index+AssetManager.STYLE_DATA]);
+ return mAssets.getPooledStringForCookie(cookie, data[index+AssetManager.STYLE_DATA]);
}
/*package*/ TypedArray(Resources resources, int[] data, int[] indices, int len) {
diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java
index 3ad357f2..2f4d69b0 100644
--- a/core/java/android/content/res/XmlBlock.java
+++ b/core/java/android/content/res/XmlBlock.java
@@ -375,7 +375,7 @@
boolean defaultValue) {
int t = nativeGetAttributeDataType(mParseState, idx);
// Note: don't attempt to convert any other types, because
- // we want to count on appt doing the conversion for us.
+ // we want to count on aapt doing the conversion for us.
if (t >= TypedValue.TYPE_FIRST_INT &&
t <= TypedValue.TYPE_LAST_INT) {
return nativeGetAttributeData(mParseState, idx) != 0;
@@ -385,7 +385,7 @@
public int getAttributeResourceValue(int idx, int defaultValue) {
int t = nativeGetAttributeDataType(mParseState, idx);
// Note: don't attempt to convert any other types, because
- // we want to count on appt doing the conversion for us.
+ // we want to count on aapt doing the conversion for us.
if (t == TypedValue.TYPE_REFERENCE) {
return nativeGetAttributeData(mParseState, idx);
}
@@ -394,7 +394,7 @@
public int getAttributeIntValue(int idx, int defaultValue) {
int t = nativeGetAttributeDataType(mParseState, idx);
// Note: don't attempt to convert any other types, because
- // we want to count on appt doing the conversion for us.
+ // we want to count on aapt doing the conversion for us.
if (t >= TypedValue.TYPE_FIRST_INT &&
t <= TypedValue.TYPE_LAST_INT) {
return nativeGetAttributeData(mParseState, idx);
@@ -404,7 +404,7 @@
public int getAttributeUnsignedIntValue(int idx, int defaultValue) {
int t = nativeGetAttributeDataType(mParseState, idx);
// Note: don't attempt to convert any other types, because
- // we want to count on appt doing the conversion for us.
+ // we want to count on aapt doing the conversion for us.
if (t >= TypedValue.TYPE_FIRST_INT &&
t <= TypedValue.TYPE_LAST_INT) {
return nativeGetAttributeData(mParseState, idx);
@@ -414,7 +414,7 @@
public float getAttributeFloatValue(int idx, float defaultValue) {
int t = nativeGetAttributeDataType(mParseState, idx);
// Note: don't attempt to convert any other types, because
- // we want to count on appt doing the conversion for us.
+ // we want to count on aapt doing the conversion for us.
if (t == TypedValue.TYPE_FLOAT) {
return Float.intBitsToFloat(
nativeGetAttributeData(mParseState, idx));
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 37bead8..ff77580 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1093,8 +1093,8 @@
*
* @see CaptureRequest#SENSOR_TEST_PATTERN_MODE
*/
- public static final Key<Byte> SENSOR_AVAILABLE_TEST_PATTERN_MODES =
- new Key<Byte>("android.sensor.availableTestPatternModes", byte.class);
+ public static final Key<int[]> SENSOR_AVAILABLE_TEST_PATTERN_MODES =
+ new Key<int[]>("android.sensor.availableTestPatternModes", int[].class);
/**
* <p>Which face detection modes are available,
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index a3fbfbe..679310a 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -1002,8 +1002,11 @@
* controls; the camera device will ignore those settings while
* USE_SCENE_MODE is active (except for FACE_PRIORITY
* scene mode). Other control entries are still active.
- * This setting can only be used if availableSceneModes !=
- * UNSUPPORTED</p>
+ * This setting can only be used if scene mode is supported
+ * (i.e. {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes} contain some modes
+ * other than DISABLED).</p>
+ *
+ * @see CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES
* @see CaptureRequest#CONTROL_MODE
*/
public static final int CONTROL_MODE_USE_SCENE_MODE = 2;
@@ -1625,38 +1628,37 @@
//
/**
- * <p>No flash on camera</p>
+ * <p>No flash on camera.</p>
* @see CaptureResult#FLASH_STATE
*/
public static final int FLASH_STATE_UNAVAILABLE = 0;
/**
- * <p>if {@link CameraCharacteristics#FLASH_INFO_AVAILABLE android.flash.info.available} is true Flash is
- * charging and cannot be fired</p>
- *
- * @see CameraCharacteristics#FLASH_INFO_AVAILABLE
+ * <p>Flash is charging and cannot be fired.</p>
* @see CaptureResult#FLASH_STATE
*/
public static final int FLASH_STATE_CHARGING = 1;
/**
- * <p>if {@link CameraCharacteristics#FLASH_INFO_AVAILABLE android.flash.info.available} is true Flash is
- * ready to fire</p>
- *
- * @see CameraCharacteristics#FLASH_INFO_AVAILABLE
+ * <p>Flash is ready to fire.</p>
* @see CaptureResult#FLASH_STATE
*/
public static final int FLASH_STATE_READY = 2;
/**
- * <p>if {@link CameraCharacteristics#FLASH_INFO_AVAILABLE android.flash.info.available} is true Flash fired
- * for this capture</p>
- *
- * @see CameraCharacteristics#FLASH_INFO_AVAILABLE
+ * <p>Flash fired for this capture.</p>
* @see CaptureResult#FLASH_STATE
*/
public static final int FLASH_STATE_FIRED = 3;
+ /**
+ * <p>Flash partially illuminated this frame. This is usually due to the next
+ * or previous frame having the flash fire, and the flash spilling into this capture
+ * due to hardware limitations.</p>
+ * @see CaptureResult#FLASH_STATE
+ */
+ public static final int FLASH_STATE_PARTIAL = 4;
+
//
// Enumeration values for CaptureResult#LENS_STATE
//
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 9bf1b98..b3bce3b 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -1164,6 +1164,7 @@
* @see #FLASH_STATE_CHARGING
* @see #FLASH_STATE_READY
* @see #FLASH_STATE_FIRED
+ * @see #FLASH_STATE_PARTIAL
*/
public static final Key<Integer> FLASH_STATE =
new Key<Integer>("android.flash.state", int.class);
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java
index 2c8a5c2..ecc461e 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDevice.java
@@ -335,7 +335,9 @@
mRepeatingRequestId = REQUEST_ID_NONE;
// Queue for deletion after in-flight requests finish
- mRepeatingRequestIdDeletedList.add(requestId);
+ if (mCaptureListenerMap.get(requestId) != null) {
+ mRepeatingRequestIdDeletedList.add(requestId);
+ }
try {
mRemoteDevice.cancelRequest(requestId);
@@ -367,8 +369,6 @@
}
mRepeatingRequestId = REQUEST_ID_NONE;
- mRepeatingRequestIdDeletedList.clear();
- mCaptureListenerMap.clear();
}
}
diff --git a/core/java/android/hardware/hdmi/HdmiCec.java b/core/java/android/hardware/hdmi/HdmiCec.java
index 38d9de4..8578a32 100644
--- a/core/java/android/hardware/hdmi/HdmiCec.java
+++ b/core/java/android/hardware/hdmi/HdmiCec.java
@@ -160,6 +160,12 @@
public static final int MESSAGE_SET_EXTERNAL_TIMER = 0xA2;
public static final int MESSAGE_ABORT = 0xFF;
+ public static final int POWER_STATUS_UNKNOWN = -1;
+ public static final int POWER_STATUS_ON = 0;
+ public static final int POWER_STATUS_STANDBY = 1;
+ public static final int POWER_TRANSIENT_TO_ON = 2;
+ public static final int POWER_TRANSIENT_TO_STANDBY = 3;
+
private static final int[] ADDRESS_TO_TYPE = {
DEVICE_TV, // ADDR_TV
DEVICE_RECORDER, // ADDR_RECORDER_1
diff --git a/core/java/android/hardware/hdmi/HdmiCecClient.java b/core/java/android/hardware/hdmi/HdmiCecClient.java
index d7f4a72..1f382e6 100644
--- a/core/java/android/hardware/hdmi/HdmiCecClient.java
+++ b/core/java/android/hardware/hdmi/HdmiCecClient.java
@@ -110,16 +110,20 @@
}
/**
- * Send <GiveDevicePowerStatus> message.
+ * Returns true if the TV or attached display is powered on.
+ * <p>
+ * The result of this method is only meaningful on playback devices (where the device
+ * type is {@link HdmiCec#DEVICE_PLAYBACK}).
+ * </p>
*
- * @param address logical address of the device to send the message to, such as
- * {@link HdmiCec#ADDR_TV}.
+ * @return true if TV is on; otherwise false.
*/
- public void sendGiveDevicePowerStatus(int address) {
+ public boolean isTvOn() {
try {
- mService.sendGiveDevicePowerStatus(mBinder, address);
+ return mService.isTvOn(mBinder);
} catch (RemoteException e) {
- Log.e(TAG, "sendGiveDevicePowerStatus threw exception ", e);
+ Log.e(TAG, "isTvOn threw exception ", e);
}
+ return false;
}
}
diff --git a/core/java/android/hardware/hdmi/HdmiCecManager.java b/core/java/android/hardware/hdmi/HdmiCecManager.java
index 575785d..10b058c 100644
--- a/core/java/android/hardware/hdmi/HdmiCecManager.java
+++ b/core/java/android/hardware/hdmi/HdmiCecManager.java
@@ -45,6 +45,9 @@
* @return {@link HdmiCecClient} instance. {@code null} on failure.
*/
public HdmiCecClient getClient(int type, HdmiCecClient.Listener listener) {
+ if (mService == null) {
+ return null;
+ }
try {
IBinder b = mService.allocateLogicalDevice(type, getListenerWrapper(listener));
return HdmiCecClient.create(mService, b);
diff --git a/core/java/android/hardware/hdmi/IHdmiCecService.aidl b/core/java/android/hardware/hdmi/IHdmiCecService.aidl
index 6fefcf8..b5df131 100644
--- a/core/java/android/hardware/hdmi/IHdmiCecService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiCecService.aidl
@@ -29,12 +29,11 @@
interface IHdmiCecService {
IBinder allocateLogicalDevice(int type, IHdmiCecListener listener);
void removeServiceListener(IBinder b, IHdmiCecListener listener);
- void setOsdName(IBinder b, String name);
void sendActiveSource(IBinder b);
void sendInactiveSource(IBinder b);
void sendImageViewOn(IBinder b);
void sendTextViewOn(IBinder b);
- void sendGiveDevicePowerStatus(IBinder b, int address);
+ boolean isTvOn(IBinder b);
void sendMessage(IBinder b, in HdmiCecMessage message);
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 81ad28b..a355d1e 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -647,6 +647,7 @@
getApplicationInfo().targetSdkVersion,
android.R.style.Theme_InputMethod,
android.R.style.Theme_Holo_InputMethod,
+ android.R.style.Theme_DeviceDefault_InputMethod,
android.R.style.Theme_DeviceDefault_InputMethod);
super.setTheme(mTheme);
super.onCreate();
diff --git a/core/java/android/net/http/CertificateChainValidator.java b/core/java/android/net/http/CertificateChainValidator.java
index 1e476fc..d06355d 100644
--- a/core/java/android/net/http/CertificateChainValidator.java
+++ b/core/java/android/net/http/CertificateChainValidator.java
@@ -16,22 +16,28 @@
package android.net.http;
-import com.android.org.conscrypt.SSLParametersImpl;
-import com.android.org.conscrypt.TrustManagerImpl;
+import android.util.Slog;
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.lang.reflect.Method;
import java.security.GeneralSecurityException;
-import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
-import javax.net.ssl.DefaultHostnameVerifier;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
-import javax.net.ssl.X509TrustManager;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509ExtendedTrustManager;
/**
* Class responsible for all server certificate validation functionality
@@ -39,28 +45,54 @@
* {@hide}
*/
public class CertificateChainValidator {
+ private static final String TAG = "CertificateChainValidator";
- /**
- * The singleton instance of the certificate chain validator
- */
- private static final CertificateChainValidator sInstance
- = new CertificateChainValidator();
+ private static class NoPreloadHolder {
+ /**
+ * The singleton instance of the certificate chain validator.
+ */
+ private static final CertificateChainValidator sInstance = new CertificateChainValidator();
- private static final DefaultHostnameVerifier sVerifier
- = new DefaultHostnameVerifier();
+ /**
+ * The singleton instance of the hostname verifier.
+ */
+ private static final HostnameVerifier sVerifier = HttpsURLConnection
+ .getDefaultHostnameVerifier();
+ }
+
+ private X509ExtendedTrustManager mTrustManager;
/**
* @return The singleton instance of the certificates chain validator
*/
public static CertificateChainValidator getInstance() {
- return sInstance;
+ return NoPreloadHolder.sInstance;
}
/**
* Creates a new certificate chain validator. This is a private constructor.
* If you need a Certificate chain validator, call getInstance().
*/
- private CertificateChainValidator() {}
+ private CertificateChainValidator() {
+ try {
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("X.509");
+ tmf.init((KeyStore) null);
+ for (TrustManager tm : tmf.getTrustManagers()) {
+ if (tm instanceof X509ExtendedTrustManager) {
+ mTrustManager = (X509ExtendedTrustManager) tm;
+ }
+ }
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("X.509 TrustManagerFactory must be available", e);
+ } catch (KeyStoreException e) {
+ throw new RuntimeException("X.509 TrustManagerFactory cannot be initialized", e);
+ }
+
+ if (mTrustManager == null) {
+ throw new RuntimeException(
+ "None of the X.509 TrustManagers are X509ExtendedTrustManager");
+ }
+ }
/**
* Performs the handshake and server certificates validation
@@ -136,14 +168,31 @@
* Handles updates to credential storage.
*/
public static void handleTrustStorageUpdate() {
-
+ TrustManagerFactory tmf;
try {
- X509TrustManager x509TrustManager = SSLParametersImpl.getDefaultX509TrustManager();
- if( x509TrustManager instanceof TrustManagerImpl ) {
- TrustManagerImpl trustManager = (TrustManagerImpl) x509TrustManager;
- trustManager.handleTrustStorageUpdate();
+ tmf = TrustManagerFactory.getInstance("X.509");
+ tmf.init((KeyStore) null);
+ } catch (NoSuchAlgorithmException e) {
+ Slog.w(TAG, "Couldn't find default X.509 TrustManagerFactory");
+ return;
+ } catch (KeyStoreException e) {
+ Slog.w(TAG, "Couldn't initialize default X.509 TrustManagerFactory", e);
+ return;
+ }
+
+ TrustManager[] tms = tmf.getTrustManagers();
+ boolean sentUpdate = false;
+ for (TrustManager tm : tms) {
+ try {
+ Method updateMethod = tm.getClass().getDeclaredMethod("handleTrustStorageUpdate");
+ updateMethod.setAccessible(true);
+ updateMethod.invoke(tm);
+ sentUpdate = true;
+ } catch (Exception e) {
}
- } catch (KeyManagementException ignored) {
+ }
+ if (!sentUpdate) {
+ Slog.w(TAG, "Didn't find a TrustManager to handle CA list update");
}
}
@@ -166,7 +215,8 @@
boolean valid = domain != null
&& !domain.isEmpty()
- && sVerifier.verify(domain, currCertificate);
+ && NoPreloadHolder.sVerifier.verify(domain,
+ new DelegatingSSLSession.CertificateWrap(currCertificate));
if (!valid) {
if (HttpLog.LOGV) {
HttpLog.v("certificate not for this host: " + domain);
@@ -175,13 +225,8 @@
}
try {
- X509TrustManager x509TrustManager = SSLParametersImpl.getDefaultX509TrustManager();
- if (x509TrustManager instanceof TrustManagerImpl) {
- TrustManagerImpl trustManager = (TrustManagerImpl) x509TrustManager;
- trustManager.checkServerTrusted(chain, authType, domain);
- } else {
- x509TrustManager.checkServerTrusted(chain, authType);
- }
+ getInstance().getTrustManager().checkServerTrusted(chain, authType,
+ new DelegatingSocketWrapper(domain));
return null; // No errors.
} catch (GeneralSecurityException e) {
if (HttpLog.LOGV) {
@@ -192,6 +237,12 @@
}
}
+ /**
+ * Returns the platform default {@link X509ExtendedTrustManager}.
+ */
+ private X509ExtendedTrustManager getTrustManager() {
+ return mTrustManager;
+ }
private void closeSocketThrowException(
SSLSocket socket, String errorMessage, String defaultErrorMessage)
@@ -217,4 +268,4 @@
throw new SSLHandshakeException(errorMessage);
}
-}
+}
\ No newline at end of file
diff --git a/core/java/android/net/http/DelegatingSSLSession.java b/core/java/android/net/http/DelegatingSSLSession.java
new file mode 100644
index 0000000..ff75b24
--- /dev/null
+++ b/core/java/android/net/http/DelegatingSSLSession.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.http;
+
+import java.security.Principal;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSessionContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.X509ExtendedTrustManager;
+
+/**
+ * This is used when only a {@code hostname} is available but usage of the new API
+ * {@link X509ExtendedTrustManager#checkServerTrusted(X509Certificate[], String, Socket)}
+ * requires a {@link SSLSocket}.
+ *
+ * @hide
+ */
+public class DelegatingSSLSession implements SSLSession {
+ protected DelegatingSSLSession() {
+ }
+
+ public static class HostnameWrap extends DelegatingSSLSession {
+ private final String mHostname;
+
+ public HostnameWrap(String hostname) {
+ mHostname = hostname;
+ }
+
+ @Override
+ public String getPeerHost() {
+ return mHostname;
+ }
+ }
+
+ public static class CertificateWrap extends DelegatingSSLSession {
+ private final Certificate mCertificate;
+
+ public CertificateWrap(Certificate certificate) {
+ mCertificate = certificate;
+ }
+
+ @Override
+ public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
+ return new Certificate[] { mCertificate };
+ }
+ }
+
+
+ @Override
+ public int getApplicationBufferSize() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getCipherSuite() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long getCreationTime() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public byte[] getId() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long getLastAccessedTime() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Certificate[] getLocalCertificates() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Principal getLocalPrincipal() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getPacketBufferSize() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public javax.security.cert.X509Certificate[] getPeerCertificateChain()
+ throws SSLPeerUnverifiedException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getPeerHost() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getPeerPort() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getProtocol() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SSLSessionContext getSessionContext() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object getValue(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String[] getValueNames() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void invalidate() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isValid() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void putValue(String name, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void removeValue(String name) {
+ throw new UnsupportedOperationException();
+ }
+}
\ No newline at end of file
diff --git a/core/java/android/net/http/DelegatingSocketWrapper.java b/core/java/android/net/http/DelegatingSocketWrapper.java
new file mode 100644
index 0000000..230d017
--- /dev/null
+++ b/core/java/android/net/http/DelegatingSocketWrapper.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.http;
+
+import java.io.IOException;
+
+import javax.net.ssl.HandshakeCompletedListener;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.X509ExtendedTrustManager;
+
+/**
+ * This is used when only a {@code hostname} is available for
+ * {@link X509ExtendedTrustManager#checkServerTrusted(java.security.cert.X509Certificate[], String, Socket)}
+ * but we want to use the new API that requires a {@link SSLSocket}.
+ */
+class DelegatingSocketWrapper extends SSLSocket {
+ private String hostname;
+
+ public DelegatingSocketWrapper(String hostname) {
+ this.hostname = hostname;
+ }
+
+ @Override
+ public String[] getSupportedCipherSuites() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String[] getEnabledCipherSuites() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setEnabledCipherSuites(String[] suites) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String[] getSupportedProtocols() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String[] getEnabledProtocols() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setEnabledProtocols(String[] protocols) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SSLSession getSession() {
+ return new DelegatingSSLSession.HostnameWrap(hostname);
+ }
+
+ @Override
+ public void addHandshakeCompletedListener(HandshakeCompletedListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void startHandshake() throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setUseClientMode(boolean mode) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean getUseClientMode() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setNeedClientAuth(boolean need) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setWantClientAuth(boolean want) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean getNeedClientAuth() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean getWantClientAuth() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setEnableSessionCreation(boolean flag) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean getEnableSessionCreation() {
+ throw new UnsupportedOperationException();
+ }
+}
\ No newline at end of file
diff --git a/core/java/android/net/http/X509TrustManagerExtensions.java b/core/java/android/net/http/X509TrustManagerExtensions.java
index db71279..830ddce 100644
--- a/core/java/android/net/http/X509TrustManagerExtensions.java
+++ b/core/java/android/net/http/X509TrustManagerExtensions.java
@@ -22,14 +22,25 @@
import java.security.cert.X509Certificate;
import java.util.List;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.X509ExtendedTrustManager;
import javax.net.ssl.X509TrustManager;
/**
* X509TrustManager wrapper exposing Android-added features.
- *
- * <p> The checkServerTrusted method allows callers to perform additional
- * verification of certificate chains after they have been successfully
- * verified by the platform.</p>
+ * <p>
+ * The checkServerTrusted method allows callers to perform additional
+ * verification of certificate chains after they have been successfully verified
+ * by the platform.
+ * </p>
+ * <p>
+ * If the returned certificate list is not needed, see also
+ * {@code X509ExtendedTrustManager#checkServerTrusted(X509Certificate[], String, java.net.Socket)}
+ * where an {@link SSLSocket} can be used to verify the given hostname during
+ * handshake using
+ * {@code SSLParameters#setEndpointIdentificationAlgorithm(String)}.
+ * </p>
*/
public class X509TrustManagerExtensions {
@@ -45,7 +56,8 @@
if (tm instanceof TrustManagerImpl) {
mDelegate = (TrustManagerImpl) tm;
} else {
- throw new IllegalArgumentException("tm is not a supported type of X509TrustManager");
+ throw new IllegalArgumentException("tm is an instance of " + tm.getClass().getName() +
+ " which is not a supported type of X509TrustManager");
}
}
@@ -61,7 +73,8 @@
*/
public List<X509Certificate> checkServerTrusted(X509Certificate[] chain, String authType,
String host) throws CertificateException {
- return mDelegate.checkServerTrusted(chain, authType, host);
+ return mDelegate.checkServerTrusted(chain, authType,
+ new DelegatingSSLSession.HostnameWrap(host));
}
/**
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index d8e8e2c..377ed88 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -211,6 +211,7 @@
private Context mContext;
private static final int INVALID_LISTENER_KEY = 0;
+ private static final int BUSY_LISTENER_KEY = -1;
private int mListenerKey = 1;
private final SparseArray mListenerMap = new SparseArray();
private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<NsdServiceInfo>();
@@ -317,71 +318,74 @@
Log.d(TAG, "Stale key " + message.arg2);
return;
}
- boolean listenerRemove = true;
NsdServiceInfo ns = getNsdService(message.arg2);
switch (message.what) {
case DISCOVER_SERVICES_STARTED:
String s = getNsdServiceInfoType((NsdServiceInfo) message.obj);
((DiscoveryListener) listener).onDiscoveryStarted(s);
- // Keep listener until stop discovery
- listenerRemove = false;
break;
case DISCOVER_SERVICES_FAILED:
+ removeListener(message.arg2);
((DiscoveryListener) listener).onStartDiscoveryFailed(getNsdServiceInfoType(ns),
message.arg1);
break;
case SERVICE_FOUND:
((DiscoveryListener) listener).onServiceFound((NsdServiceInfo) message.obj);
- // Keep listener until stop discovery
- listenerRemove = false;
break;
case SERVICE_LOST:
((DiscoveryListener) listener).onServiceLost((NsdServiceInfo) message.obj);
- // Keep listener until stop discovery
- listenerRemove = false;
break;
case STOP_DISCOVERY_FAILED:
+ removeListener(message.arg2);
((DiscoveryListener) listener).onStopDiscoveryFailed(getNsdServiceInfoType(ns),
message.arg1);
break;
case STOP_DISCOVERY_SUCCEEDED:
+ removeListener(message.arg2);
((DiscoveryListener) listener).onDiscoveryStopped(getNsdServiceInfoType(ns));
break;
case REGISTER_SERVICE_FAILED:
+ removeListener(message.arg2);
((RegistrationListener) listener).onRegistrationFailed(ns, message.arg1);
break;
case REGISTER_SERVICE_SUCCEEDED:
((RegistrationListener) listener).onServiceRegistered(
(NsdServiceInfo) message.obj);
- // Keep listener until unregister
- listenerRemove = false;
break;
case UNREGISTER_SERVICE_FAILED:
+ removeListener(message.arg2);
((RegistrationListener) listener).onUnregistrationFailed(ns, message.arg1);
break;
case UNREGISTER_SERVICE_SUCCEEDED:
+ removeListener(message.arg2);
((RegistrationListener) listener).onServiceUnregistered(ns);
break;
case RESOLVE_SERVICE_FAILED:
+ removeListener(message.arg2);
((ResolveListener) listener).onResolveFailed(ns, message.arg1);
break;
case RESOLVE_SERVICE_SUCCEEDED:
+ removeListener(message.arg2);
((ResolveListener) listener).onServiceResolved((NsdServiceInfo) message.obj);
break;
default:
Log.d(TAG, "Ignored " + message);
break;
}
- if (listenerRemove) {
- removeListener(message.arg2);
- }
}
}
+ // if the listener is already in the map, reject it. Otherwise, add it and
+ // return its key.
+
private int putListener(Object listener, NsdServiceInfo s) {
if (listener == null) return INVALID_LISTENER_KEY;
int key;
synchronized (mMapLock) {
+ int valueIndex = mListenerMap.indexOfValue(listener);
+ if (valueIndex != -1) {
+ return BUSY_LISTENER_KEY;
+ }
do {
key = mListenerKey++;
} while (key == INVALID_LISTENER_KEY);
@@ -422,7 +426,6 @@
return INVALID_LISTENER_KEY;
}
-
private String getNsdServiceInfoType(NsdServiceInfo s) {
if (s == null) return "?";
return s.getServiceType();
@@ -449,14 +452,18 @@
* Register a service to be discovered by other services.
*
* <p> The function call immediately returns after sending a request to register service
- * to the framework. The application is notified of a success to initiate
- * discovery through the callback {@link RegistrationListener#onServiceRegistered} or a failure
+ * to the framework. The application is notified of a successful registration
+ * through the callback {@link RegistrationListener#onServiceRegistered} or a failure
* through {@link RegistrationListener#onRegistrationFailed}.
*
+ * <p> The application should call {@link #unregisterService} when the service
+ * registration is no longer required, and/or whenever the application is stopped.
+ *
* @param serviceInfo The service being registered
* @param protocolType The service discovery protocol
* @param listener The listener notifies of a successful registration and is used to
* unregister this service through a call on {@link #unregisterService}. Cannot be null.
+ * Cannot be in use for an active service registration.
*/
public void registerService(NsdServiceInfo serviceInfo, int protocolType,
RegistrationListener listener) {
@@ -473,8 +480,11 @@
if (protocolType != PROTOCOL_DNS_SD) {
throw new IllegalArgumentException("Unsupported protocol");
}
- mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, putListener(listener, serviceInfo),
- serviceInfo);
+ int key = putListener(listener, serviceInfo);
+ if (key == BUSY_LISTENER_KEY) {
+ throw new IllegalArgumentException("listener already in use");
+ }
+ mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, key, serviceInfo);
}
/**
@@ -484,7 +494,11 @@
*
* @param listener This should be the listener object that was passed to
* {@link #registerService}. It identifies the service that should be unregistered
- * and notifies of a successful unregistration.
+ * and notifies of a successful or unsuccessful unregistration via the listener
+ * callbacks. In API versions 20 and above, the listener object may be used for
+ * another service registration once the callback has been called. In API versions <= 19,
+ * there is no entirely reliable way to know when a listener may be re-used, and a new
+ * listener should be created for each service registration request.
*/
public void unregisterService(RegistrationListener listener) {
int id = getListenerKey(listener);
@@ -514,12 +528,16 @@
* <p> Upon failure to start, service discovery is not active and application does
* not need to invoke {@link #stopServiceDiscovery}
*
+ * <p> The application should call {@link #stopServiceDiscovery} when discovery of this
+ * service type is no longer required, and/or whenever the application is paused or
+ * stopped.
+ *
* @param serviceType The service type being discovered. Examples include "_http._tcp" for
* http services or "_ipp._tcp" for printers
* @param protocolType The service discovery protocol
* @param listener The listener notifies of a successful discovery and is used
* to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}.
- * Cannot be null.
+ * Cannot be null. Cannot be in use for an active service discovery.
*/
public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) {
if (listener == null) {
@@ -535,11 +553,17 @@
NsdServiceInfo s = new NsdServiceInfo();
s.setServiceType(serviceType);
- mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, putListener(listener, s), s);
+
+ int key = putListener(listener, s);
+ if (key == BUSY_LISTENER_KEY) {
+ throw new IllegalArgumentException("listener already in use");
+ }
+
+ mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, key, s);
}
/**
- * Stop service discovery initiated with {@link #discoverServices}. An active service
+ * Stop service discovery initiated with {@link #discoverServices}. An active service
* discovery is notified to the application with {@link DiscoveryListener#onDiscoveryStarted}
* and it stays active until the application invokes a stop service discovery. A successful
* stop is notified to with a call to {@link DiscoveryListener#onDiscoveryStopped}.
@@ -548,7 +572,11 @@
* {@link DiscoveryListener#onStopDiscoveryFailed}.
*
* @param listener This should be the listener object that was passed to {@link #discoverServices}.
- * It identifies the discovery that should be stopped and notifies of a successful stop.
+ * It identifies the discovery that should be stopped and notifies of a successful or
+ * unsuccessful stop. In API versions 20 and above, the listener object may be used for
+ * another service discovery once the callback has been called. In API versions <= 19,
+ * there is no entirely reliable way to know when a listener may be re-used, and a new
+ * listener should be created for each service discovery request.
*/
public void stopServiceDiscovery(DiscoveryListener listener) {
int id = getListenerKey(listener);
@@ -568,6 +596,7 @@
*
* @param serviceInfo service to be resolved
* @param listener to receive callback upon success or failure. Cannot be null.
+ * Cannot be in use for an active service resolution.
*/
public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) {
if (TextUtils.isEmpty(serviceInfo.getServiceName()) ||
@@ -577,8 +606,13 @@
if (listener == null) {
throw new IllegalArgumentException("listener cannot be null");
}
- mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, putListener(listener, serviceInfo),
- serviceInfo);
+
+ int key = putListener(listener, serviceInfo);
+
+ if (key == BUSY_LISTENER_KEY) {
+ throw new IllegalArgumentException("listener already in use");
+ }
+ mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, key, serviceInfo);
}
/** Internal use only @hide */
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 6e6c06d..1192a45 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -28,13 +28,13 @@
*/
interface IUserManager {
UserInfo createUser(in String name, int flags);
- UserInfo createRelatedUser(in String name, int flags, int relatedUserId);
+ UserInfo createProfileForUser(in String name, int flags, int userHandle);
boolean removeUser(int userHandle);
void setUserName(int userHandle, String name);
void setUserIcon(int userHandle, in Bitmap icon);
Bitmap getUserIcon(int userHandle);
List<UserInfo> getUsers(boolean excludeDying);
- List<UserInfo> getRelatedUsers(int userHandle);
+ List<UserInfo> getProfiles(int userHandle);
UserInfo getUserInfo(int userHandle);
boolean isRestricted();
void setGuestEnabled(boolean enable);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 057f516..3241693 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -16,10 +16,11 @@
package android.os;
-import android.net.LocalSocketAddress;
import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
import android.util.Log;
-import dalvik.system.Zygote;
+
+import com.android.internal.os.Zygote;
import java.io.BufferedWriter;
import java.io.DataInputStream;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 1ec5cd5..520a08c 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -410,20 +410,29 @@
}
/**
- * Creates a user with the specified name and options.
+ * Renamed, just present to avoid multi project commit.
+ * TODO delete.
+ * @hide
+ */
+ public UserInfo createRelatedUser(String name, int flags, int relatedUserId) {
+ return createProfileForUser(name, flags, relatedUserId);
+ }
+
+ /**
+ * Creates a user with the specified name and options as a profile of another user.
* Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
*
* @param name the user's name
* @param flags flags that identify the type of user and other properties.
* @see UserInfo
- * @param relatedUserId new user will be related to this user id.
+ * @param userHandle new user will be a profile of this use.
*
* @return the UserInfo object for the created user, or null if the user could not be created.
* @hide
*/
- public UserInfo createRelatedUser(String name, int flags, int relatedUserId) {
+ public UserInfo createProfileForUser(String name, int flags, int userHandle) {
try {
- return mService.createRelatedUser(name, flags, relatedUserId);
+ return mService.createProfileForUser(name, flags, userHandle);
} catch (RemoteException re) {
Log.w(TAG, "Could not create a user", re);
return null;
@@ -454,15 +463,26 @@
}
/**
- * Returns information for all users related to userId
- * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
- * @param userHandle users related to this user id will be returned.
- * @return the list of related users.
+ * Renaming, left to avoid multi project commit.
+ * TODO Delete.
* @hide
*/
public List<UserInfo> getRelatedUsers(int userHandle) {
+ return getProfiles(userHandle);
+ }
+
+ /**
+ * Returns list of the profiles of userHandle including
+ * userHandle itself.
+ *
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+ * @param userHandle profiles of this user will be returned.
+ * @return the list of profiles.
+ * @hide
+ */
+ public List<UserInfo> getProfiles(int userHandle) {
try {
- return mService.getRelatedUsers(userHandle);
+ return mService.getProfiles(userHandle);
} catch (RemoteException re) {
Log.w(TAG, "Could not get user list", re);
return null;
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index bd576af..ae24968 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -173,6 +173,10 @@
*/
public static final String EXTRA_MEDIA_GENRE = "android.intent.extra.genre";
/**
+ * The name of the Intent-extra used to define the playlist.
+ */
+ public static final String EXTRA_MEDIA_PLAYLIST = "android.intent.extra.playlist";
+ /**
* The name of the Intent-extra used to define the radio channel.
*/
public static final String EXTRA_MEDIA_RADIO_CHANNEL = "android.intent.extra.radio_channel";
diff --git a/core/java/android/provider/SearchIndexablesContract.java b/core/java/android/provider/SearchIndexablesContract.java
index b8635b8..05f3a1c 100644
--- a/core/java/android/provider/SearchIndexablesContract.java
+++ b/core/java/android/provider/SearchIndexablesContract.java
@@ -73,7 +73,8 @@
public static final String[] INDEXABLES_RAW_COLUMNS = new String[] {
RawData.COLUMN_RANK,
RawData.COLUMN_TITLE,
- RawData.COLUMN_SUMMARY,
+ RawData.COLUMN_SUMMARY_ON,
+ RawData.COLUMN_SUMMARY_OFF,
RawData.COLUMN_KEYWORDS,
RawData.COLUMN_SCREEN_TITLE,
RawData.COLUMN_CLASS_NAME,
@@ -123,9 +124,14 @@
public static final String COLUMN_TITLE = "title";
/**
- * Summary's raw data.
+ * Summary's raw data when the data is "ON".
*/
- public static final String COLUMN_SUMMARY = "summary";
+ public static final String COLUMN_SUMMARY_ON = "summaryOn";
+
+ /**
+ * Summary's raw data when the data is "OFF".
+ */
+ public static final String COLUMN_SUMMARY_OFF = "summaryOff";
/**
* Keywords' raw data.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 7777334..7062933 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6098,21 +6098,18 @@
"lock_screen_show_notifications";
/**
- * Defines global zen mode. One of ZEN_MODE_OFF, ZEN_MODE_LIMITED, ZEN_MODE_FULL.
+ * Defines global zen mode. ZEN_MODE_OFF or ZEN_MODE_ON.
*
* @hide
*/
public static final String ZEN_MODE = "zen_mode";
/** @hide */ public static final int ZEN_MODE_OFF = 0;
- /** @hide */ public static final int ZEN_MODE_LIMITED = 1;
- /** @hide */ public static final int ZEN_MODE_FULL = 2;
+ /** @hide */ public static final int ZEN_MODE_ON = 1;
/** @hide */ public static String zenModeToString(int mode) {
if (mode == ZEN_MODE_OFF) return "ZEN_MODE_OFF";
- if (mode == ZEN_MODE_LIMITED) return "ZEN_MODE_LIMITED";
- if (mode == ZEN_MODE_FULL) return "ZEN_MODE_FULL";
- throw new IllegalArgumentException("Invalid zen mode: " + mode);
+ return "ZEN_MODE_ON";
}
/**
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 7647c22..de9eeff 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -153,11 +153,11 @@
private final Handler mHandler = new Handler();
private IBinder mWindowToken;
private Window mWindow;
- private WindowManager mWindowManager;
- private boolean mInteractive = false;
+ private boolean mInteractive;
private boolean mLowProfile = true;
- private boolean mFullscreen = false;
+ private boolean mFullscreen;
private boolean mScreenBright = true;
+ private boolean mStarted;
private boolean mFinished;
private boolean mCanDoze;
private boolean mDozing;
@@ -340,7 +340,7 @@
* @return The current window manager, or null if the dream is not started.
*/
public WindowManager getWindowManager() {
- return mWindowManager;
+ return mWindow != null ? mWindow.getWindowManager() : null;
}
/**
@@ -623,7 +623,7 @@
* @hide experimental
*/
public DozeHardware getDozeHardware() {
- if (mCanDoze && mDozeHardware == null) {
+ if (mCanDoze && mDozeHardware == null && mWindowToken != null) {
try {
IDozeHardware hardware = mSandman.getDozeHardware(mWindowToken);
if (hardware != null) {
@@ -701,24 +701,25 @@
* Must run on mHandler.
*/
private final void detach() {
- if (mWindow == null) {
- // already detached!
- return;
+ if (mStarted) {
+ if (mDebug) Slog.v(TAG, "detach(): Calling onDreamingStopped()");
+ mStarted = false;
+ onDreamingStopped();
}
- if (mDebug) Slog.v(TAG, "detach(): Calling onDreamingStopped()");
- onDreamingStopped();
+ if (mWindow != null) {
+ // force our window to be removed synchronously
+ if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager");
+ mWindow.getWindowManager().removeViewImmediate(mWindow.getDecorView());
+ mWindow = null;
+ }
- if (mDebug) Slog.v(TAG, "detach(): Removing window from window manager");
-
- // force our window to be removed synchronously
- mWindowManager.removeViewImmediate(mWindow.getDecorView());
- // the following will print a log message if it finds any other leaked windows
- WindowManagerGlobal.getInstance().closeAll(mWindowToken,
- this.getClass().getName(), "Dream");
-
- mWindow = null;
- mWindowToken = null;
+ if (mWindowToken != null) {
+ // the following will print a log message if it finds any other leaked windows
+ WindowManagerGlobal.getInstance().closeAll(mWindowToken,
+ this.getClass().getName(), "Dream");
+ mWindowToken = null;
+ }
}
/**
@@ -746,12 +747,13 @@
if (mDebug) Slog.v(TAG, "Attached on thread " + Thread.currentThread().getId());
mWindowToken = windowToken;
+ mCanDoze = canDoze;
+
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
mWindow.requestFeature(Window.FEATURE_NO_TITLE);
mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000));
mWindow.setFormat(PixelFormat.OPAQUE);
- mCanDoze = canDoze;
if (mDebug) Slog.v(TAG, String.format("Attaching window token: %s to window of type %s",
windowToken, WindowManager.LayoutParams.TYPE_DREAM));
@@ -769,26 +771,28 @@
| (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0)
);
mWindow.setAttributes(lp);
-
- if (mDebug) Slog.v(TAG, "Created and attached window: " + mWindow);
-
mWindow.setWindowManager(null, windowToken, "dream", true);
- mWindowManager = mWindow.getWindowManager();
- if (mDebug) Slog.v(TAG, "Window added on thread " + Thread.currentThread().getId());
applySystemUiVisibilityFlags(
(mLowProfile ? View.SYSTEM_UI_FLAG_LOW_PROFILE : 0),
View.SYSTEM_UI_FLAG_LOW_PROFILE);
- getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
+
+ try {
+ getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes());
+ } catch (WindowManager.BadTokenException ex) {
+ // This can happen because the dream manager service will remove the token
+ // immediately without necessarily waiting for the dream to start.
+ // We should receive a finish message soon.
+ Slog.i(TAG, "attach() called after window token already removed, dream will "
+ + "finish soon");
+ mWindow = null;
+ return;
+ }
// start it up
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
- onDreamingStarted();
- }
- });
+ if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
+ mStarted = true;
+ onDreamingStarted();
}
private void safelyFinish() {
@@ -831,7 +835,7 @@
WindowManager.LayoutParams lp = mWindow.getAttributes();
lp.flags = applyFlags(lp.flags, flags, mask);
mWindow.setAttributes(lp);
- mWindowManager.updateViewLayout(mWindow.getDecorView(), lp);
+ mWindow.getWindowManager().updateViewLayout(mWindow.getDecorView(), lp);
}
}
diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl
index 425fdc1..d4b29d8 100644
--- a/core/java/android/service/notification/INotificationListener.aidl
+++ b/core/java/android/service/notification/INotificationListener.aidl
@@ -21,6 +21,7 @@
/** @hide */
oneway interface INotificationListener
{
+ void onListenerConnected(in String[] notificationKeys);
void onNotificationPosted(in StatusBarNotification notification);
void onNotificationRemoved(in StatusBarNotification notification);
}
\ No newline at end of file
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index cf862b8..050e1a0 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -83,6 +83,17 @@
*/
public abstract void onNotificationRemoved(StatusBarNotification sbn);
+ /**
+ * Implement this method to learn about when the listener is enabled and connected to
+ * the notification manager. You are safe to call {@link #getActiveNotifications(String[])
+ * at this time.
+ *
+ * @param notificationKeys The notification keys for all currently posted notifications.
+ */
+ public void onListenerConnected(String[] notificationKeys) {
+ // optional
+ }
+
private final INotificationManager getNotificationInterface() {
if (mNoMan == null) {
mNoMan = INotificationManager.Stub.asInterface(
@@ -132,9 +143,23 @@
* {@see #cancelNotification(String, String, int)}
*/
public final void cancelAllNotifications() {
+ cancelNotifications(null /*all*/);
+ }
+
+ /**
+ * Inform the notification manager about dismissal of specific notifications.
+ * <p>
+ * Use this if your listener has a user interface that allows the user to dismiss
+ * multiple notifications at once.
+ *
+ * @param keys Notifications to dismiss, or {@code null} to dismiss all.
+ *
+ * {@see #cancelNotification(String, String, int)}
+ */
+ public final void cancelNotifications(String[] keys) {
if (!isBound()) return;
try {
- getNotificationInterface().cancelAllNotificationsFromListener(mWrapper);
+ getNotificationInterface().cancelNotificationsFromListener(mWrapper, keys);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
}
@@ -142,14 +167,43 @@
/**
* Request the list of outstanding notifications (that is, those that are visible to the
- * current user). Useful when starting up and you don't know what's already been posted.
+ * current user). Useful when you don't know what's already been posted.
*
* @return An array of active notifications.
*/
public StatusBarNotification[] getActiveNotifications() {
+ return getActiveNotifications(null /*all*/);
+ }
+
+ /**
+ * Request the list of outstanding notifications (that is, those that are visible to the
+ * current user). Useful when you don't know what's already been posted.
+ *
+ * @param keys A specific list of notification keys, or {@code null} for all.
+ * @return An array of active notifications.
+ */
+ public StatusBarNotification[] getActiveNotifications(String[] keys) {
if (!isBound()) return null;
try {
- return getNotificationInterface().getActiveNotificationsFromListener(mWrapper);
+ return getNotificationInterface().getActiveNotificationsFromListener(mWrapper, keys);
+ } catch (android.os.RemoteException ex) {
+ Log.v(TAG, "Unable to contact notification manager", ex);
+ }
+ return null;
+ }
+
+ /**
+ * Request the list of outstanding notification keys(that is, those that are visible to the
+ * current user). You can use the notification keys for subsequent retrieval via
+ * {@link #getActiveNotifications(String[]) or dismissal via
+ * {@link #cancelNotifications(String[]).
+ *
+ * @return An array of active notification keys.
+ */
+ public String[] getActiveNotificationKeys() {
+ if (!isBound()) return null;
+ try {
+ return getNotificationInterface().getActiveNotificationKeysFromListener(mWrapper);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
}
@@ -189,5 +243,13 @@
Log.w(TAG, "Error running onNotificationRemoved", t);
}
}
+ @Override
+ public void onListenerConnected(String[] notificationKeys) {
+ try {
+ NotificationListenerService.this.onListenerConnected(notificationKeys);
+ } catch (Throwable t) {
+ Log.w(TAG, "Error running onListenerConnected", t);
+ }
+ }
}
}
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index b5b9e14..7f15ab8 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -29,6 +29,7 @@
private final String pkg;
private final int id;
private final String tag;
+ private final String key;
private final int uid;
private final String basePkg;
@@ -68,8 +69,8 @@
this.notification = notification;
this.user = user;
this.notification.setUser(user);
-
this.postTime = postTime;
+ this.key = key();
}
public StatusBarNotification(Parcel in) {
@@ -88,6 +89,11 @@
this.user = UserHandle.readFromParcel(in);
this.notification.setUser(this.user);
this.postTime = in.readLong();
+ this.key = key();
+ }
+
+ private String key() {
+ return pkg + '|' + basePkg + '|' + id + '|' + tag + '|' + uid;
}
public void writeToParcel(Parcel out, int flags) {
@@ -148,9 +154,9 @@
@Override
public String toString() {
return String.format(
- "StatusBarNotification(pkg=%s user=%s id=%d tag=%s score=%d: %s)",
+ "StatusBarNotification(pkg=%s user=%s id=%d tag=%s score=%d key=%s: %s)",
this.pkg, this.user, this.id, this.tag,
- this.score, this.notification);
+ this.score, this.key, this.notification);
}
/** Convenience method to check the notification's flags for
@@ -230,4 +236,11 @@
public int getScore() {
return score;
}
+
+ /**
+ * A unique instance key for this notification record.
+ */
+ public String getKey() {
+ return key;
+ }
}
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/service/trust/ITrustAgentService.aidl
similarity index 64%
copy from core/java/android/view/DisplayList.java
copy to core/java/android/service/trust/ITrustAgentService.aidl
index ed52803..863a249 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/service/trust/ITrustAgentService.aidl
@@ -13,13 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package android.service.trust;
-package android.view;
+import android.os.Bundle;
+import android.service.trust.ITrustAgentServiceCallback;
-/** TODO: Remove once frameworks/webview is updated
- * @hide
+/**
+ * Communication channel from TrustManagerService to the TrustAgent.
+ * @hide
*/
-public class DisplayList {
- /** @hide */
- public static final int STATUS_DONE = 0x0;
+oneway interface ITrustAgentService {
+ void onUnlockAttempt(boolean successful);
+ void setCallback(ITrustAgentServiceCallback callback);
}
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
similarity index 64%
rename from core/java/android/view/DisplayList.java
rename to core/java/android/service/trust/ITrustAgentServiceCallback.aidl
index ed52803..c346771 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/service/trust/ITrustAgentServiceCallback.aidl
@@ -13,13 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package android.service.trust;
-package android.view;
+import android.os.Bundle;
+import android.os.UserHandle;
-/** TODO: Remove once frameworks/webview is updated
- * @hide
+/**
+ * Communication channel from the TrustAgentService back to TrustManagerService.
+ * @hide
*/
-public class DisplayList {
- /** @hide */
- public static final int STATUS_DONE = 0x0;
+oneway interface ITrustAgentServiceCallback {
+ void enableTrust(String message, long durationMs, boolean initiatedByUser);
+ void revokeTrust();
}
diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java
new file mode 100644
index 0000000..d5ce429
--- /dev/null
+++ b/core/java/android/service/trust/TrustAgentService.java
@@ -0,0 +1,148 @@
+/**
+ * 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.service.trust;
+
+import android.annotation.SdkConstant;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+
+/**
+ * A service that notifies the system about whether it believes the environment of the device
+ * to be trusted.
+ *
+ * <p>To extend this class, you must declare the service in your manifest file with
+ * the {@link android.Manifest.permission#BIND_TRUST_AGENT_SERVICE} permission
+ * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
+ * <pre>
+ * <service android:name=".TrustAgent"
+ * android:label="@string/service_name"
+ * android:permission="android.permission.BIND_TRUST_AGENT_SERVICE">
+ * <intent-filter>
+ * <action android:name="android.service.trust.TrustAgentService" />
+ * </intent-filter>
+ * <meta-data android:name="android.service.trust.trustagent"
+ * android:value="@xml/trust_agent" />
+ * </service></pre>
+ *
+ * <p>The associated meta-data file can specify an activity that is accessible through Settings
+ * and should allow configuring the trust agent, as defined in
+ * {@link android.R.styleable#TrustAgent}. For example:</p>
+ *
+ * <pre>
+ * <trust_agent xmlns:android="http://schemas.android.com/apk/res/android"
+ * android:settingsActivity=".TrustAgentSettings" /></pre>
+ */
+public class TrustAgentService extends Service {
+ private final String TAG = TrustAgentService.class.getSimpleName() +
+ "[" + getClass().getSimpleName() + "]";
+
+ /**
+ * The {@link Intent} that must be declared as handled by the service.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String SERVICE_INTERFACE
+ = "android.service.trust.TrustAgentService";
+
+ /**
+ * The name of the {@code meta-data} tag pointing to additional configuration of the trust
+ * agent.
+ */
+ public static final String TRUST_AGENT_META_DATA = "android.service.trust.trustagent";
+
+ private static final int MSG_UNLOCK_ATTEMPT = 1;
+
+ private static final boolean DEBUG = false;
+
+ private ITrustAgentServiceCallback mCallback;
+
+ private Handler mHandler = new Handler() {
+ public void handleMessage(android.os.Message msg) {
+ switch (msg.what) {
+ case MSG_UNLOCK_ATTEMPT:
+ onUnlockAttempt(msg.arg1 != 0);
+ break;
+ }
+ };
+ };
+
+ /**
+ * Called when the user attempted to authenticate on the device.
+ *
+ * @param successful true if the attempt succeeded
+ */
+ protected void onUnlockAttempt(boolean successful) {
+ }
+
+ private void onError(String msg) {
+ Slog.v(TAG, "Remote exception while " + msg);
+ }
+
+ /**
+ * Call to enable trust on the device.
+ *
+ * @param message describes why the device is trusted, e.g. "Trusted by location".
+ * @param durationMs amount of time in milliseconds to keep the device in a trusted state. Trust
+ * for this agent will automatically be revoked when the timeout expires.
+ * @param initiatedByUser indicates that the user has explicitly initiated an action that proves
+ * the user is about to use the device.
+ */
+ protected final void enableTrust(String message, long durationMs, boolean initiatedByUser) {
+ if (mCallback != null) {
+ try {
+ mCallback.enableTrust(message, durationMs, initiatedByUser);
+ } catch (RemoteException e) {
+ onError("calling enableTrust()");
+ }
+ }
+ }
+
+ /**
+ * Call to revoke trust on the device.
+ */
+ protected final void revokeTrust() {
+ if (mCallback != null) {
+ try {
+ mCallback.revokeTrust();
+ } catch (RemoteException e) {
+ onError("calling revokeTrust()");
+ }
+ }
+ }
+
+ @Override
+ public final IBinder onBind(Intent intent) {
+ if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
+ return new TrustAgentServiceWrapper();
+ }
+
+ private final class TrustAgentServiceWrapper extends ITrustAgentService.Stub {
+ @Override
+ public void onUnlockAttempt(boolean successful) {
+ mHandler.obtainMessage(MSG_UNLOCK_ATTEMPT, successful ? 1 : 0, 0)
+ .sendToTarget();
+ }
+
+ public void setCallback(ITrustAgentServiceCallback callback) {
+ mCallback = callback;
+ }
+ }
+
+}
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 06935ae..77ef1da 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -21,6 +21,7 @@
import android.text.style.WrapTogetherSpan;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
import java.lang.ref.WeakReference;
@@ -401,7 +402,7 @@
if (mBlockEndLines == null) {
// Initial creation of the array, no test on previous block ending line
- mBlockEndLines = new int[ArrayUtils.idealIntArraySize(1)];
+ mBlockEndLines = ArrayUtils.newUnpaddedIntArray(1);
mBlockEndLines[mNumberOfBlocks] = line;
mNumberOfBlocks++;
return;
@@ -409,13 +410,7 @@
final int previousBlockEndLine = mBlockEndLines[mNumberOfBlocks - 1];
if (line > previousBlockEndLine) {
- if (mNumberOfBlocks == mBlockEndLines.length) {
- // Grow the array if needed
- int[] blockEndLines = new int[ArrayUtils.idealIntArraySize(mNumberOfBlocks + 1)];
- System.arraycopy(mBlockEndLines, 0, blockEndLines, 0, mNumberOfBlocks);
- mBlockEndLines = blockEndLines;
- }
- mBlockEndLines[mNumberOfBlocks] = line;
+ mBlockEndLines = GrowingArrayUtils.append(mBlockEndLines, mNumberOfBlocks, line);
mNumberOfBlocks++;
}
}
@@ -483,9 +478,9 @@
}
if (newNumberOfBlocks > mBlockEndLines.length) {
- final int newSize = ArrayUtils.idealIntArraySize(newNumberOfBlocks);
- int[] blockEndLines = new int[newSize];
- int[] blockIndices = new int[newSize];
+ int[] blockEndLines = ArrayUtils.newUnpaddedIntArray(
+ Math.max(mBlockEndLines.length * 2, newNumberOfBlocks));
+ int[] blockIndices = new int[blockEndLines.length];
System.arraycopy(mBlockEndLines, 0, blockEndLines, 0, firstBlock);
System.arraycopy(mBlockIndices, 0, blockIndices, 0, firstBlock);
System.arraycopy(mBlockEndLines, lastBlock + 1,
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
index c80321c..2fcc597 100644
--- a/core/java/android/text/Html.java
+++ b/core/java/android/text/Html.java
@@ -211,7 +211,7 @@
private static String getOpenParaTagWithDirection(Spanned text, int start, int end) {
final int len = end - start;
- final byte[] levels = new byte[ArrayUtils.idealByteArraySize(len)];
+ final byte[] levels = ArrayUtils.newUnpaddedByteArray(len);
final char[] buffer = TextUtils.obtain(len);
TextUtils.getChars(text, start, end, buffer, 0);
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 9dfd383..4bfcaff 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -31,6 +31,7 @@
import android.text.style.TabStopSpan;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
import java.util.Arrays;
@@ -403,14 +404,9 @@
// construction
if (mLineBackgroundSpans.spanStarts[j] >= end ||
mLineBackgroundSpans.spanEnds[j] <= start) continue;
- if (spansLength == spans.length) {
- // The spans array needs to be expanded
- int newSize = ArrayUtils.idealObjectArraySize(2 * spansLength);
- ParagraphStyle[] newSpans = new ParagraphStyle[newSize];
- System.arraycopy(spans, 0, newSpans, 0, spansLength);
- spans = newSpans;
- }
- spans[spansLength++] = mLineBackgroundSpans.spans[j];
+ spans = GrowingArrayUtils.append(
+ spans, spansLength, mLineBackgroundSpans.spans[j]);
+ spansLength++;
}
}
}
diff --git a/core/java/android/text/MeasuredText.java b/core/java/android/text/MeasuredText.java
index 101d6a2..f8e3c83 100644
--- a/core/java/android/text/MeasuredText.java
+++ b/core/java/android/text/MeasuredText.java
@@ -98,10 +98,10 @@
mPos = 0;
if (mWidths == null || mWidths.length < len) {
- mWidths = new float[ArrayUtils.idealFloatArraySize(len)];
+ mWidths = ArrayUtils.newUnpaddedFloatArray(len);
}
if (mChars == null || mChars.length < len) {
- mChars = new char[ArrayUtils.idealCharArraySize(len)];
+ mChars = ArrayUtils.newUnpaddedCharArray(len);
}
TextUtils.getChars(text, start, end, mChars, 0);
@@ -130,7 +130,7 @@
mEasy = true;
} else {
if (mLevels == null || mLevels.length < len) {
- mLevels = new byte[ArrayUtils.idealByteArraySize(len)];
+ mLevels = ArrayUtils.newUnpaddedByteArray(len);
}
int bidiRequest;
if (textDir == TextDirectionHeuristics.LTR) {
diff --git a/core/java/android/text/PackedIntVector.java b/core/java/android/text/PackedIntVector.java
index d87f600..546ab44 100644
--- a/core/java/android/text/PackedIntVector.java
+++ b/core/java/android/text/PackedIntVector.java
@@ -17,6 +17,7 @@
package android.text;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
/**
@@ -252,9 +253,9 @@
*/
private final void growBuffer() {
final int columns = mColumns;
- int newsize = size() + 1;
- newsize = ArrayUtils.idealIntArraySize(newsize * columns) / columns;
- int[] newvalues = new int[newsize * columns];
+ int[] newvalues = ArrayUtils.newUnpaddedIntArray(
+ GrowingArrayUtils.growSize(size()) * columns);
+ int newsize = newvalues.length / columns;
final int[] valuegap = mValueGap;
final int rowgapstart = mRowGapStart;
diff --git a/core/java/android/text/PackedObjectVector.java b/core/java/android/text/PackedObjectVector.java
index a29df09..b777e16 100644
--- a/core/java/android/text/PackedObjectVector.java
+++ b/core/java/android/text/PackedObjectVector.java
@@ -17,6 +17,9 @@
package android.text;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
class PackedObjectVector<E>
{
@@ -32,12 +35,11 @@
PackedObjectVector(int columns)
{
mColumns = columns;
- mRows = ArrayUtils.idealIntArraySize(0) / mColumns;
+ mValues = EmptyArray.OBJECT;
+ mRows = 0;
mRowGapStart = 0;
mRowGapLength = mRows;
-
- mValues = new Object[mRows * mColumns];
}
public E
@@ -109,10 +111,9 @@
private void
growBuffer()
{
- int newsize = size() + 1;
- newsize = ArrayUtils.idealIntArraySize(newsize * mColumns) / mColumns;
- Object[] newvalues = new Object[newsize * mColumns];
-
+ Object[] newvalues = ArrayUtils.newUnpaddedObjectArray(
+ GrowingArrayUtils.growSize(size()) * mColumns);
+ int newsize = newvalues.length / mColumns;
int after = mRows - (mRowGapStart + mRowGapLength);
System.arraycopy(mValues, 0, newvalues, 0, mColumns * mRowGapStart);
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index b55cd6a..f440853 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -21,6 +21,9 @@
import android.util.Log;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
import java.lang.reflect.Array;
@@ -54,19 +57,17 @@
if (srclen < 0) throw new StringIndexOutOfBoundsException();
- int len = ArrayUtils.idealCharArraySize(srclen + 1);
- mText = new char[len];
+ mText = ArrayUtils.newUnpaddedCharArray(GrowingArrayUtils.growSize(srclen));
mGapStart = srclen;
- mGapLength = len - srclen;
+ mGapLength = mText.length - srclen;
TextUtils.getChars(text, start, end, mText, 0);
mSpanCount = 0;
- int alloc = ArrayUtils.idealIntArraySize(0);
- mSpans = new Object[alloc];
- mSpanStarts = new int[alloc];
- mSpanEnds = new int[alloc];
- mSpanFlags = new int[alloc];
+ mSpans = EmptyArray.OBJECT;
+ mSpanStarts = EmptyArray.INT;
+ mSpanEnds = EmptyArray.INT;
+ mSpanFlags = EmptyArray.INT;
if (text instanceof Spanned) {
Spanned sp = (Spanned) text;
@@ -130,12 +131,14 @@
private void resizeFor(int size) {
final int oldLength = mText.length;
- final int newLength = ArrayUtils.idealCharArraySize(size + 1);
- final int delta = newLength - oldLength;
- if (delta == 0) return;
+ if (size + 1 <= oldLength) {
+ return;
+ }
- char[] newText = new char[newLength];
+ char[] newText = ArrayUtils.newUnpaddedCharArray(GrowingArrayUtils.growSize(size));
System.arraycopy(mText, 0, newText, 0, mGapStart);
+ final int newLength = newText.length;
+ final int delta = newLength - oldLength;
final int after = oldLength - (mGapStart + mGapLength);
System.arraycopy(mText, oldLength - after, newText, newLength - after, after);
mText = newText;
@@ -679,28 +682,10 @@
}
}
- if (mSpanCount + 1 >= mSpans.length) {
- int newsize = ArrayUtils.idealIntArraySize(mSpanCount + 1);
- Object[] newspans = new Object[newsize];
- int[] newspanstarts = new int[newsize];
- int[] newspanends = new int[newsize];
- int[] newspanflags = new int[newsize];
-
- System.arraycopy(mSpans, 0, newspans, 0, mSpanCount);
- System.arraycopy(mSpanStarts, 0, newspanstarts, 0, mSpanCount);
- System.arraycopy(mSpanEnds, 0, newspanends, 0, mSpanCount);
- System.arraycopy(mSpanFlags, 0, newspanflags, 0, mSpanCount);
-
- mSpans = newspans;
- mSpanStarts = newspanstarts;
- mSpanEnds = newspanends;
- mSpanFlags = newspanflags;
- }
-
- mSpans[mSpanCount] = what;
- mSpanStarts[mSpanCount] = start;
- mSpanEnds[mSpanCount] = end;
- mSpanFlags[mSpanCount] = flags;
+ mSpans = GrowingArrayUtils.append(mSpans, mSpanCount, what);
+ mSpanStarts = GrowingArrayUtils.append(mSpanStarts, mSpanCount, start);
+ mSpanEnds = GrowingArrayUtils.append(mSpanEnds, mSpanCount, end);
+ mSpanFlags = GrowingArrayUtils.append(mSpanFlags, mSpanCount, flags);
mSpanCount++;
if (send) sendSpanAdded(what, nstart, nend);
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index 456a3e5..d114d32 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -17,6 +17,9 @@
package android.text;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
import java.lang.reflect.Array;
@@ -29,9 +32,8 @@
else
mText = source.toString().substring(start, end);
- int initial = ArrayUtils.idealIntArraySize(0);
- mSpans = new Object[initial];
- mSpanData = new int[initial * 3];
+ mSpans = EmptyArray.OBJECT;
+ mSpanData = EmptyArray.INT;
if (source instanceof Spanned) {
Spanned sp = (Spanned) source;
@@ -115,9 +117,9 @@
}
if (mSpanCount + 1 >= mSpans.length) {
- int newsize = ArrayUtils.idealIntArraySize(mSpanCount + 1);
- Object[] newtags = new Object[newsize];
- int[] newdata = new int[newsize * 3];
+ Object[] newtags = ArrayUtils.newUnpaddedObjectArray(
+ GrowingArrayUtils.growSize(mSpanCount));
+ int[] newdata = new int[newtags.length * 3];
System.arraycopy(mSpans, 0, newtags, 0, mSpanCount);
System.arraycopy(mSpanData, 0, newdata, 0, mSpanCount * 3);
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index e7d6fda..535eee1 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -26,6 +26,7 @@
import android.util.Log;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
/**
* StaticLayout is a Layout for text that will not be edited after it
@@ -130,9 +131,8 @@
mEllipsizedWidth = outerwidth;
}
- mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)];
- mLineDirections = new Directions[
- ArrayUtils.idealIntArraySize(2 * mColumns)];
+ mLineDirections = ArrayUtils.newUnpaddedArray(Directions.class, 2 * mColumns);
+ mLines = new int[mLineDirections.length];
mMaximumVisibleLineCount = maxLines;
mMeasured = MeasuredText.obtain();
@@ -149,8 +149,8 @@
super(text, null, 0, null, 0, 0);
mColumns = COLUMNS_ELLIPSIZE;
- mLines = new int[ArrayUtils.idealIntArraySize(2 * mColumns)];
- mLineDirections = new Directions[ArrayUtils.idealIntArraySize(2 * mColumns)];
+ mLineDirections = ArrayUtils.newUnpaddedArray(Directions.class, 2 * mColumns);
+ mLines = new int[mLineDirections.length];
// FIXME This is never recycled
mMeasured = MeasuredText.obtain();
}
@@ -215,8 +215,7 @@
if (chooseHt.length != 0) {
if (chooseHtv == null ||
chooseHtv.length < chooseHt.length) {
- chooseHtv = new int[ArrayUtils.idealIntArraySize(
- chooseHt.length)];
+ chooseHtv = ArrayUtils.newUnpaddedIntArray(chooseHt.length);
}
for (int i = 0; i < chooseHt.length; i++) {
@@ -599,16 +598,16 @@
int[] lines = mLines;
if (want >= lines.length) {
- int nlen = ArrayUtils.idealIntArraySize(want + 1);
- int[] grow = new int[nlen];
- System.arraycopy(lines, 0, grow, 0, lines.length);
- mLines = grow;
- lines = grow;
-
- Directions[] grow2 = new Directions[nlen];
+ Directions[] grow2 = ArrayUtils.newUnpaddedArray(
+ Directions.class, GrowingArrayUtils.growSize(want));
System.arraycopy(mLineDirections, 0, grow2, 0,
mLineDirections.length);
mLineDirections = grow2;
+
+ int[] grow = new int[grow2.length];
+ System.arraycopy(lines, 0, grow, 0, lines.length);
+ mLines = grow;
+ lines = grow;
}
if (chooseHt != null) {
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 1fecf81..d892f19 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -153,7 +153,7 @@
if (mCharsValid) {
if (mChars == null || mChars.length < mLen) {
- mChars = new char[ArrayUtils.idealCharArraySize(mLen)];
+ mChars = ArrayUtils.newUnpaddedCharArray(mLen);
}
TextUtils.getChars(text, start, limit, mChars, 0);
if (hasReplacement) {
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 596ca8c..f06ae71 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -1321,7 +1321,7 @@
}
if (buf == null || buf.length < len)
- buf = new char[ArrayUtils.idealCharArraySize(len)];
+ buf = ArrayUtils.newUnpaddedCharArray(len);
return buf;
}
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index df1d4cd..9a0b7fc 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -16,6 +16,8 @@
package android.util;
+import libcore.util.EmptyArray;
+
import java.util.Collection;
import java.util.Map;
import java.util.Set;
@@ -234,8 +236,8 @@
* will grow once items are added to it.
*/
public ArrayMap() {
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
mSize = 0;
}
@@ -244,8 +246,8 @@
*/
public ArrayMap(int capacity) {
if (capacity == 0) {
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
} else {
allocArrays(capacity);
}
@@ -253,8 +255,8 @@
}
private ArrayMap(boolean immutable) {
- mHashes = EMPTY_IMMUTABLE_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
mSize = 0;
}
@@ -275,8 +277,8 @@
public void clear() {
if (mSize > 0) {
freeArrays(mHashes, mArray, mSize);
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
mSize = 0;
}
}
@@ -540,8 +542,8 @@
// Now empty.
if (DEBUG) Log.d(TAG, "remove: shrink from " + mHashes.length + " to 0");
freeArrays(mHashes, mArray, mSize);
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
mSize = 0;
} else {
if (mHashes.length > (BASE_SIZE*2) && mSize < mHashes.length/3) {
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index 3c695e9..9d4b720 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -16,6 +16,8 @@
package android.util;
+import libcore.util.EmptyArray;
+
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
@@ -222,8 +224,8 @@
* will grow once items are added to it.
*/
public ArraySet() {
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
mSize = 0;
}
@@ -232,8 +234,8 @@
*/
public ArraySet(int capacity) {
if (capacity == 0) {
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
} else {
allocArrays(capacity);
}
@@ -258,8 +260,8 @@
public void clear() {
if (mSize != 0) {
freeArrays(mHashes, mArray, mSize);
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
mSize = 0;
}
}
@@ -413,8 +415,8 @@
// Now empty.
if (DEBUG) Log.d(TAG, "remove: shrink from " + mHashes.length + " to 0");
freeArrays(mHashes, mArray, mSize);
- mHashes = ContainerHelpers.EMPTY_INTS;
- mArray = ContainerHelpers.EMPTY_OBJECTS;
+ mHashes = EmptyArray.INT;
+ mArray = EmptyArray.OBJECT;
mSize = 0;
} else {
if (mHashes.length > (BASE_SIZE*2) && mSize < mHashes.length/3) {
diff --git a/core/java/android/util/ContainerHelpers.java b/core/java/android/util/ContainerHelpers.java
index 624c4bd..4e5fefb 100644
--- a/core/java/android/util/ContainerHelpers.java
+++ b/core/java/android/util/ContainerHelpers.java
@@ -17,10 +17,6 @@
package android.util;
class ContainerHelpers {
- static final boolean[] EMPTY_BOOLEANS = new boolean[0];
- static final int[] EMPTY_INTS = new int[0];
- static final long[] EMPTY_LONGS = new long[0];
- static final Object[] EMPTY_OBJECTS = new Object[0];
// This is Arrays.binarySearch(), but doesn't do any argument validation.
static int binarySearch(int[] array, int size, int value) {
diff --git a/core/java/android/util/LongArray.java b/core/java/android/util/LongArray.java
index d5f15f0..54a6882 100644
--- a/core/java/android/util/LongArray.java
+++ b/core/java/android/util/LongArray.java
@@ -17,6 +17,7 @@
package android.util;
import com.android.internal.util.ArrayUtils;
+import libcore.util.EmptyArray;
/**
* Implements a growing array of long primitives.
@@ -41,10 +42,9 @@
*/
public LongArray(int initialCapacity) {
if (initialCapacity == 0) {
- mValues = ContainerHelpers.EMPTY_LONGS;
+ mValues = EmptyArray.LONG;
} else {
- initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
- mValues = new long[initialCapacity];
+ mValues = ArrayUtils.newUnpaddedLongArray(initialCapacity);
}
mSize = 0;
}
@@ -97,7 +97,7 @@
final int targetCap = currentSize + (currentSize < (MIN_CAPACITY_INCREMENT / 2) ?
MIN_CAPACITY_INCREMENT : currentSize >> 1);
final int newCapacity = targetCap > minCapacity ? targetCap : minCapacity;
- final long[] newValues = new long[ArrayUtils.idealLongArraySize(newCapacity)];
+ final long[] newValues = ArrayUtils.newUnpaddedLongArray(newCapacity);
System.arraycopy(mValues, 0, newValues, 0, currentSize);
mValues = newValues;
}
diff --git a/core/java/android/util/LongSparseArray.java b/core/java/android/util/LongSparseArray.java
index dab853a..6b45ff4 100644
--- a/core/java/android/util/LongSparseArray.java
+++ b/core/java/android/util/LongSparseArray.java
@@ -17,6 +17,9 @@
package android.util;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
/**
* SparseArray mapping longs to Objects. Unlike a normal array of Objects,
@@ -70,12 +73,11 @@
*/
public LongSparseArray(int initialCapacity) {
if (initialCapacity == 0) {
- mKeys = ContainerHelpers.EMPTY_LONGS;
- mValues = ContainerHelpers.EMPTY_OBJECTS;
+ mKeys = EmptyArray.LONG;
+ mValues = EmptyArray.OBJECT;
} else {
- initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
- mKeys = new long[initialCapacity];
- mValues = new Object[initialCapacity];
+ mKeys = ArrayUtils.newUnpaddedLongArray(initialCapacity);
+ mValues = ArrayUtils.newUnpaddedObjectArray(initialCapacity);
}
mSize = 0;
}
@@ -202,28 +204,8 @@
i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
}
- if (mSize >= mKeys.length) {
- int n = ArrayUtils.idealLongArraySize(mSize + 1);
-
- long[] nkeys = new long[n];
- Object[] nvalues = new Object[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- if (mSize - i != 0) {
- // Log.e("SparseArray", "move " + (mSize - i));
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
+ mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
+ mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
mSize++;
}
}
@@ -353,24 +335,9 @@
gc();
}
- int pos = mSize;
- if (pos >= mKeys.length) {
- int n = ArrayUtils.idealLongArraySize(pos + 1);
-
- long[] nkeys = new long[n];
- Object[] nvalues = new Object[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
+ mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
+ mValues = GrowingArrayUtils.append(mValues, mSize, value);
+ mSize++;
}
/**
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
index b8073dd..a361457 100644
--- a/core/java/android/util/LongSparseLongArray.java
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -17,6 +17,9 @@
package android.util;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
/**
* Map of {@code long} to {@code long}. Unlike a normal array of longs, there
@@ -62,12 +65,11 @@
*/
public LongSparseLongArray(int initialCapacity) {
if (initialCapacity == 0) {
- mKeys = ContainerHelpers.EMPTY_LONGS;
- mValues = ContainerHelpers.EMPTY_LONGS;
+ mKeys = EmptyArray.LONG;
+ mValues = EmptyArray.LONG;
} else {
- initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
- mKeys = new long[initialCapacity];
- mValues = new long[initialCapacity];
+ mKeys = ArrayUtils.newUnpaddedLongArray(initialCapacity);
+ mValues = new long[mKeys.length];
}
mSize = 0;
}
@@ -140,17 +142,8 @@
} else {
i = ~i;
- if (mSize >= mKeys.length) {
- growKeyAndValueArrays(mSize + 1);
- }
-
- if (mSize - i != 0) {
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
+ mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
+ mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
mSize++;
}
}
@@ -234,27 +227,9 @@
return;
}
- int pos = mSize;
- if (pos >= mKeys.length) {
- growKeyAndValueArrays(pos + 1);
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
- }
-
- private void growKeyAndValueArrays(int minNeededSize) {
- int n = ArrayUtils.idealLongArraySize(minNeededSize);
-
- long[] nkeys = new long[n];
- long[] nvalues = new long[n];
-
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
+ mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
+ mValues = GrowingArrayUtils.append(mValues, mSize, value);
+ mSize++;
}
/**
diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java
index 0f8da44..13cc88b 100644
--- a/core/java/android/util/Patterns.java
+++ b/core/java/android/util/Patterns.java
@@ -28,7 +28,12 @@
* List accurate as of 2011/07/18. List taken from:
* http://data.iana.org/TLD/tlds-alpha-by-domain.txt
* This pattern is auto-generated by frameworks/ex/common/tools/make-iana-tld-pattern.py
+ *
+ * @deprecated Due to the recent profileration of gTLDs, this API is
+ * expected to become out-of-date very quickly. Therefore it is now
+ * deprecated.
*/
+ @Deprecated
public static final String TOP_LEVEL_DOMAIN_STR =
"((aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
+ "|(biz|b[abdefghijmnorstvwyz])"
@@ -59,7 +64,9 @@
/**
* Regular expression pattern to match all IANA top-level domains.
+ * @deprecated This API is deprecated. See {@link #TOP_LEVEL_DOMAIN_STR}.
*/
+ @Deprecated
public static final Pattern TOP_LEVEL_DOMAIN =
Pattern.compile(TOP_LEVEL_DOMAIN_STR);
@@ -68,7 +75,10 @@
* List accurate as of 2011/07/18. List taken from:
* http://data.iana.org/TLD/tlds-alpha-by-domain.txt
* This pattern is auto-generated by frameworks/ex/common/tools/make-iana-tld-pattern.py
+ *
+ * @deprecated This API is deprecated. See {@link #TOP_LEVEL_DOMAIN_STR}.
*/
+ @Deprecated
public static final String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL =
"(?:"
+ "(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
@@ -107,6 +117,24 @@
public static final String GOOD_IRI_CHAR =
"a-zA-Z0-9\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
+ public static final Pattern IP_ADDRESS
+ = Pattern.compile(
+ "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
+ + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
+ + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
+ + "|[1-9][0-9]|[0-9]))");
+
+ /**
+ * RFC 1035 Section 2.3.4 limits the labels to a maximum 63 octets.
+ */
+ private static final String IRI
+ = "[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "\\-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}";
+
+ private static final String HOST_NAME = IRI + "(?:\\." + IRI + ")+";
+
+ public static final Pattern DOMAIN_NAME
+ = Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")");
+
/**
* Regular expression pattern to match most part of RFC 3987
* Internationalized URLs, aka IRIs. Commonly used Unicode characters are
@@ -116,13 +144,7 @@
"((?:(http|https|Http|Https|rtsp|Rtsp):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
+ "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
+ "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
- + "((?:(?:[" + GOOD_IRI_CHAR + "][" + GOOD_IRI_CHAR + "\\-]{0,64}\\.)+" // named host
- + TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL
- + "|(?:(?:25[0-5]|2[0-4]" // or ip address
- + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(?:25[0-5]|2[0-4][0-9]"
- + "|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1]"
- + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
- + "|[1-9][0-9]|[0-9])))"
+ + "(?:" + DOMAIN_NAME + ")"
+ "(?:\\:\\d{1,5})?)" // plus option port number
+ "(\\/(?:(?:[" + GOOD_IRI_CHAR + "\\;\\/\\?\\:\\@\\&\\=\\#\\~" // plus option query params
+ "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
@@ -130,19 +152,6 @@
// input. This is to stop foo.sure from
// matching as foo.su
- public static final Pattern IP_ADDRESS
- = Pattern.compile(
- "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
- + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
- + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
- + "|[1-9][0-9]|[0-9]))");
-
- public static final Pattern DOMAIN_NAME
- = Pattern.compile(
- "(((([" + GOOD_IRI_CHAR + "][" + GOOD_IRI_CHAR + "\\-]*)*[" + GOOD_IRI_CHAR + "]\\.)+"
- + TOP_LEVEL_DOMAIN + ")|"
- + IP_ADDRESS + ")");
-
public static final Pattern EMAIL_ADDRESS
= Pattern.compile(
"[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" +
@@ -159,7 +168,7 @@
* might be phone numbers in arbitrary text, not for validating whether
* something is in fact a phone number. It will miss many things that
* are legitimate phone numbers.
- *
+ *
* <p> The pattern matches the following:
* <ul>
* <li>Optionally, a + sign followed immediately by one or more digits. Spaces, dots, or dashes
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index 46d9d45..92e874f 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -17,6 +17,9 @@
package android.util;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
/**
* SparseArrays map integers to Objects. Unlike a normal array of Objects,
@@ -70,12 +73,11 @@
*/
public SparseArray(int initialCapacity) {
if (initialCapacity == 0) {
- mKeys = ContainerHelpers.EMPTY_INTS;
- mValues = ContainerHelpers.EMPTY_OBJECTS;
+ mKeys = EmptyArray.INT;
+ mValues = EmptyArray.OBJECT;
} else {
- initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
- mKeys = new int[initialCapacity];
- mValues = new Object[initialCapacity];
+ mValues = ArrayUtils.newUnpaddedObjectArray(initialCapacity);
+ mKeys = new int[mValues.length];
}
mSize = 0;
}
@@ -215,28 +217,8 @@
i = ~ContainerHelpers.binarySearch(mKeys, mSize, key);
}
- if (mSize >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(mSize + 1);
-
- int[] nkeys = new int[n];
- Object[] nvalues = new Object[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- if (mSize - i != 0) {
- // Log.e("SparseArray", "move " + (mSize - i));
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
+ mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
+ mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
mSize++;
}
}
@@ -368,24 +350,9 @@
gc();
}
- int pos = mSize;
- if (pos >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(pos + 1);
-
- int[] nkeys = new int[n];
- Object[] nvalues = new Object[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
+ mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
+ mValues = GrowingArrayUtils.append(mValues, mSize, value);
+ mSize++;
}
/**
diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java
index f59ef0f6d..e293b1f 100644
--- a/core/java/android/util/SparseBooleanArray.java
+++ b/core/java/android/util/SparseBooleanArray.java
@@ -17,6 +17,9 @@
package android.util;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
/**
* SparseBooleanArrays map integers to booleans.
@@ -57,12 +60,11 @@
*/
public SparseBooleanArray(int initialCapacity) {
if (initialCapacity == 0) {
- mKeys = ContainerHelpers.EMPTY_INTS;
- mValues = ContainerHelpers.EMPTY_BOOLEANS;
+ mKeys = EmptyArray.INT;
+ mValues = EmptyArray.BOOLEAN;
} else {
- initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
- mKeys = new int[initialCapacity];
- mValues = new boolean[initialCapacity];
+ mKeys = ArrayUtils.newUnpaddedIntArray(initialCapacity);
+ mValues = new boolean[mKeys.length];
}
mSize = 0;
}
@@ -135,28 +137,8 @@
} else {
i = ~i;
- if (mSize >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(mSize + 1);
-
- int[] nkeys = new int[n];
- boolean[] nvalues = new boolean[n];
-
- // Log.e("SparseBooleanArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- if (mSize - i != 0) {
- // Log.e("SparseBooleanArray", "move " + (mSize - i));
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
+ mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
+ mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
mSize++;
}
}
@@ -245,24 +227,9 @@
return;
}
- int pos = mSize;
- if (pos >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(pos + 1);
-
- int[] nkeys = new int[n];
- boolean[] nvalues = new boolean[n];
-
- // Log.e("SparseBooleanArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
+ mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
+ mValues = GrowingArrayUtils.append(mValues, mSize, value);
+ mSize++;
}
/**
diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java
index 4f5ca07..2b85a21 100644
--- a/core/java/android/util/SparseIntArray.java
+++ b/core/java/android/util/SparseIntArray.java
@@ -17,6 +17,9 @@
package android.util;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
/**
* SparseIntArrays map integers to integers. Unlike a normal array of integers,
@@ -60,12 +63,11 @@
*/
public SparseIntArray(int initialCapacity) {
if (initialCapacity == 0) {
- mKeys = ContainerHelpers.EMPTY_INTS;
- mValues = ContainerHelpers.EMPTY_INTS;
+ mKeys = EmptyArray.INT;
+ mValues = EmptyArray.INT;
} else {
- initialCapacity = ArrayUtils.idealIntArraySize(initialCapacity);
- mKeys = new int[initialCapacity];
- mValues = new int[initialCapacity];
+ mKeys = ArrayUtils.newUnpaddedIntArray(initialCapacity);
+ mValues = new int[mKeys.length];
}
mSize = 0;
}
@@ -138,28 +140,8 @@
} else {
i = ~i;
- if (mSize >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(mSize + 1);
-
- int[] nkeys = new int[n];
- int[] nvalues = new int[n];
-
- // Log.e("SparseIntArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- if (mSize - i != 0) {
- // Log.e("SparseIntArray", "move " + (mSize - i));
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
+ mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
+ mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
mSize++;
}
}
@@ -243,24 +225,9 @@
return;
}
- int pos = mSize;
- if (pos >= mKeys.length) {
- int n = ArrayUtils.idealIntArraySize(pos + 1);
-
- int[] nkeys = new int[n];
- int[] nvalues = new int[n];
-
- // Log.e("SparseIntArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
+ mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
+ mValues = GrowingArrayUtils.append(mValues, mSize, value);
+ mSize++;
}
/**
diff --git a/core/java/android/util/SparseLongArray.java b/core/java/android/util/SparseLongArray.java
index 39fc8a3..0166c4a 100644
--- a/core/java/android/util/SparseLongArray.java
+++ b/core/java/android/util/SparseLongArray.java
@@ -17,6 +17,9 @@
package android.util;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
+
+import libcore.util.EmptyArray;
/**
* SparseLongArrays map integers to longs. Unlike a normal array of longs,
@@ -60,12 +63,11 @@
*/
public SparseLongArray(int initialCapacity) {
if (initialCapacity == 0) {
- mKeys = ContainerHelpers.EMPTY_INTS;
- mValues = ContainerHelpers.EMPTY_LONGS;
+ mKeys = EmptyArray.INT;
+ mValues = EmptyArray.LONG;
} else {
- initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
- mKeys = new int[initialCapacity];
- mValues = new long[initialCapacity];
+ mValues = ArrayUtils.newUnpaddedLongArray(initialCapacity);
+ mKeys = new int[mValues.length];
}
mSize = 0;
}
@@ -138,17 +140,8 @@
} else {
i = ~i;
- if (mSize >= mKeys.length) {
- growKeyAndValueArrays(mSize + 1);
- }
-
- if (mSize - i != 0) {
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = value;
+ mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
+ mValues = GrowingArrayUtils.insert(mValues, mSize, i, value);
mSize++;
}
}
@@ -232,27 +225,9 @@
return;
}
- int pos = mSize;
- if (pos >= mKeys.length) {
- growKeyAndValueArrays(pos + 1);
- }
-
- mKeys[pos] = key;
- mValues[pos] = value;
- mSize = pos + 1;
- }
-
- private void growKeyAndValueArrays(int minNeededSize) {
- int n = ArrayUtils.idealLongArraySize(minNeededSize);
-
- int[] nkeys = new int[n];
- long[] nvalues = new long[n];
-
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
+ mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
+ mValues = GrowingArrayUtils.append(mValues, mSize, value);
+ mSize++;
}
/**
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index abae068..477c994 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -52,7 +52,7 @@
*/
final class AccessibilityInteractionController {
- private static final boolean ENFORCE_NODE_TREE_CONSISTENT = Build.IS_DEBUGGABLE;
+ private static final boolean ENFORCE_NODE_TREE_CONSISTENT = false;
private final ArrayList<AccessibilityNodeInfo> mTempAccessibilityNodeInfoList =
new ArrayList<AccessibilityNodeInfo>();
diff --git a/core/java/android/view/GLRenderer.java b/core/java/android/view/GLRenderer.java
index 90824ab..d6e1781 100644
--- a/core/java/android/view/GLRenderer.java
+++ b/core/java/android/view/GLRenderer.java
@@ -555,6 +555,32 @@
}
@Override
+ public void invokeFunctor(long functor, boolean waitForCompletion) {
+ boolean needsContext = !isEnabled() || checkRenderContext() == SURFACE_STATE_ERROR;
+ boolean hasContext = !needsContext;
+
+ if (needsContext) {
+ GLRendererEglContext managedContext =
+ (GLRendererEglContext) sEglContextStorage.get();
+ if (managedContext != null) {
+ usePbufferSurface(managedContext.getContext());
+ hasContext = true;
+ }
+ }
+
+ try {
+ nInvokeFunctor(functor, hasContext);
+ } finally {
+ if (needsContext) {
+ sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
+ EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ }
+ }
+ }
+
+ private static native void nInvokeFunctor(long functor, boolean hasContext);
+
+ @Override
void destroyHardwareResources(final View view) {
if (view != null) {
safelyRun(new Runnable() {
@@ -1096,8 +1122,7 @@
}
if (checkRenderContext() != SURFACE_STATE_ERROR) {
- int status = mCanvas.invokeFunctors(mRedrawClip);
- handleFunctorStatus(attachInfo, status);
+ mCanvas.invokeFunctors(mRedrawClip);
}
}
}
@@ -1203,7 +1228,7 @@
private RenderNode buildDisplayList(View view, HardwareCanvas canvas) {
if (mDrawDelta <= 0) {
- return view.mDisplayList;
+ return view.mRenderNode;
}
view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
@@ -1214,12 +1239,12 @@
canvas.clearLayerUpdates();
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
- RenderNode displayList = view.getDisplayList();
+ RenderNode renderNode = view.getDisplayList();
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
endBuildDisplayListProfiling(buildDisplayListStartTime);
- return displayList;
+ return renderNode;
}
private Rect beginFrame(HardwareCanvas canvas, Rect dirty, int surfaceState) {
@@ -1301,7 +1326,6 @@
mProfileData[mProfileCurrentFrame + 1] = total;
}
- handleFunctorStatus(attachInfo, status);
return status;
}
@@ -1337,26 +1361,6 @@
}
}
- private void handleFunctorStatus(View.AttachInfo attachInfo, int status) {
- // If the draw flag is set, functors will be invoked while executing
- // the tree of display lists
- if ((status & RenderNode.STATUS_DRAW) != 0) {
- if (mRedrawClip.isEmpty()) {
- attachInfo.mViewRootImpl.invalidate();
- } else {
- attachInfo.mViewRootImpl.invalidateChildInParent(null, mRedrawClip);
- mRedrawClip.setEmpty();
- }
- }
-
- if ((status & RenderNode.STATUS_INVOKE) != 0 ||
- attachInfo.mHandler.hasCallbacks(mFunctorsRunnable)) {
- attachInfo.mHandler.removeCallbacks(mFunctorsRunnable);
- mFunctorsRunnable.attachInfo = attachInfo;
- attachInfo.mHandler.postDelayed(mFunctorsRunnable, FUNCTOR_PROCESS_DELAY);
- }
- }
-
@Override
void detachFunctor(long functor) {
if (mCanvas != null) {
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index f695b20..233f846 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -23,7 +23,7 @@
/**
* Hardware accelerated canvas.
- *
+ *
* @hide
*/
public abstract class HardwareCanvas extends Canvas {
@@ -40,7 +40,7 @@
/**
* Invoked before any drawing operation is performed in this canvas.
- *
+ *
* @param dirty The dirty rectangle to update, can be null.
* @return {@link RenderNode#STATUS_DREW} if anything was drawn (such as a call to clear
* the canvas).
@@ -70,13 +70,11 @@
* Draws the specified display list onto this canvas.
*
* @param displayList The display list to replay.
- * @param dirty The dirty region to redraw in the next pass, matters only
- * if this method returns {@link RenderNode#STATUS_DRAW}, can be null.
+ * @param dirty Ignored, can be null.
* @param flags Optional flags about drawing, see {@link RenderNode} for
* the possible flags.
*
- * @return One of {@link RenderNode#STATUS_DONE}, {@link RenderNode#STATUS_DRAW}, or
- * {@link RenderNode#STATUS_INVOKE}, or'd with {@link RenderNode#STATUS_DREW}
+ * @return One of {@link RenderNode#STATUS_DONE} or {@link RenderNode#STATUS_DREW}
* if anything was drawn.
*
* @hide
@@ -101,9 +99,8 @@
* This function may return true if an invalidation is needed after the call.
*
* @param drawGLFunction A native function pointer
- *
- * @return One of {@link RenderNode#STATUS_DONE}, {@link RenderNode#STATUS_DRAW} or
- * {@link RenderNode#STATUS_INVOKE}
+ *
+ * @return {@link RenderNode#STATUS_DONE}
*
* @hide
*/
@@ -114,11 +111,10 @@
/**
* Invoke all the functors who requested to be invoked during the previous frame.
- *
- * @param dirty The region to redraw when the functors return {@link RenderNode#STATUS_DRAW}
- *
- * @return One of {@link RenderNode#STATUS_DONE}, {@link RenderNode#STATUS_DRAW} or
- * {@link RenderNode#STATUS_INVOKE}
+ *
+ * @param dirty Ignored
+ *
+ * @return Ignored
*
* @hide
*/
@@ -154,7 +150,7 @@
/**
* Indicates that the specified layer must be updated as soon as possible.
- *
+ *
* @param layer The layer to update
*
* @see #clearLayerUpdates()
@@ -187,7 +183,7 @@
/**
* Removes all enqueued layer updates.
- *
+ *
* @see #pushLayerUpdate(HardwareLayer)
*
* @hide
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 34efcf5..4f646e1 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -438,6 +438,17 @@
abstract void attachFunctor(View.AttachInfo attachInfo, long functor);
/**
+ * Schedules the functor for execution in either kModeProcess or
+ * kModeProcessNoContext, depending on whether or not there is an EGLContext.
+ *
+ * @param functor The native functor to invoke
+ * @param waitForCompletion If true, this will not return until the functor
+ * has invoked. If false, the functor may be invoked
+ * asynchronously.
+ */
+ public abstract void invokeFunctor(long functor, boolean waitForCompletion);
+
+ /**
* Initializes the hardware renderer for the specified surface and setup the
* renderer for drawing, if needed. This is invoked when the ViewAncestor has
* potentially lost the hardware renderer. The hardware renderer should be
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 0b12cbe..ae5f37e 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -579,6 +579,18 @@
}
/**
+ * Determines whether the input device supports the given source or sources.
+ *
+ * @param source The input source or sources to check against. This can be a generic device
+ * type such as {@link InputDevice#SOURCE_MOUSE}, a more generic device class, such as
+ * {@link InputDevice#SOURCE_CLASS_POINTER}, or a combination of sources bitwise ORed together.
+ * @return Whether the device can produce all of the given sources.
+ */
+ public boolean supportsSource(int source) {
+ return (mSources & source) == source;
+ }
+
+ /**
* Gets the keyboard type.
* @return The keyboard type.
*/
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index c4fac46..e19bda9 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -590,6 +590,7 @@
Object[] args = mConstructorArgs;
args[1] = attrs;
+ constructor.setAccessible(true);
final View view = constructor.newInstance(args);
if (view instanceof ViewStub) {
// always use ourselves when inflating ViewStub later
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 60fb7ac..26eaef8 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.NonNull;
import android.graphics.Matrix;
import android.graphics.Outline;
@@ -196,18 +197,20 @@
}
/**
- * Starts recording the display list. All operations performed on the
- * returned canvas are recorded and stored in this display list.
+ * Starts recording a display list for the render node. All
+ * operations performed on the returned canvas are recorded and
+ * stored in this display list.
*
- * Calling this method will mark the display list invalid until
- * {@link #end()} is called. Only valid display lists can be replayed.
+ * Calling this method will mark the render node invalid until
+ * {@link #end(HardwareRenderer, HardwareCanvas)} is called.
+ * Only valid render nodes can be replayed.
*
- * @param width The width of the display list's viewport
- * @param height The height of the display list's viewport
+ * @param width The width of the recording viewport
+ * @param height The height of the recording viewport
*
* @return A canvas to record drawing operations.
*
- * @see #end()
+ * @see #end(HardwareRenderer, HardwareCanvas)
* @see #isValid()
*/
public HardwareCanvas start(int width, int height) {
@@ -269,8 +272,8 @@
}
/**
- * Returns whether the display list is currently usable. If this returns false,
- * the display list should be re-recorded prior to replaying it.
+ * Returns whether the RenderNode's display list content is currently usable.
+ * If this returns false, the display list should be re-recorded prior to replaying it.
*
* @return boolean true if the display list is able to be replayed, false otherwise.
*/
@@ -284,7 +287,23 @@
}
///////////////////////////////////////////////////////////////////////////
- // DisplayList Property Setters
+ // Matrix manipulation
+ ///////////////////////////////////////////////////////////////////////////
+
+ public boolean hasIdentityMatrix() {
+ return nHasIdentityMatrix(mNativeDisplayList);
+ }
+
+ public void getMatrix(@NonNull Matrix outMatrix) {
+ nGetTransformMatrix(mNativeDisplayList, outMatrix.native_instance);
+ }
+
+ public void getInverseMatrix(@NonNull Matrix outMatrix) {
+ nGetInverseTransformMatrix(mNativeDisplayList, outMatrix.native_instance);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // RenderProperty Setters
///////////////////////////////////////////////////////////////////////////
/**
@@ -301,7 +320,7 @@
}
/**
- * Set whether the display list should clip itself to its bounds. This property is controlled by
+ * Set whether the Render node should clip itself to its bounds. This property is controlled by
* the view's parent.
*
* @param clipToBounds true if the display list should clip to its bounds
@@ -312,9 +331,7 @@
/**
* Sets whether the display list should be drawn immediately after the
- * closest ancestor display list where isolateZVolume is true. If the
- * display list itself satisfies this constraint, changing this attribute
- * has no effect on drawing order.
+ * closest ancestor display list containing a projection receiver.
*
* @param shouldProject true if the display list should be projected onto a
* containing volume.
@@ -361,13 +378,18 @@
}
/**
+ * Controls the RenderNode's circular reveal clip.
+ */
+ public void setRevealClip(boolean shouldClip, boolean inverseClip,
+ float x, float y, float radius) {
+ nSetRevealClip(mNativeDisplayList, shouldClip, inverseClip, x, y, radius);
+ }
+
+ /**
* Set the static matrix on the display list. The specified matrix is combined with other
* transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.)
*
* @param matrix A transform matrix to apply to this display list
- *
- * @see #getMatrix(android.graphics.Matrix)
- * @see #getMatrix()
*/
public void setStaticMatrix(Matrix matrix) {
nSetStaticMatrix(mNativeDisplayList, matrix.native_instance);
@@ -605,28 +627,6 @@
}
/**
- * Sets all of the transform-related values of the display list
- *
- * @param alpha The alpha value of the display list
- * @param translationX The translationX value of the display list
- * @param translationY The translationY value of the display list
- * @param rotation The rotation value of the display list
- * @param rotationX The rotationX value of the display list
- * @param rotationY The rotationY value of the display list
- * @param scaleX The scaleX value of the display list
- * @param scaleY The scaleY value of the display list
- *
- * @hide
- */
- public void setTransformationInfo(float alpha,
- float translationX, float translationY, float translationZ,
- float rotation, float rotationX, float rotationY, float scaleX, float scaleY) {
- nSetTransformationInfo(mNativeDisplayList, alpha,
- translationX, translationY, translationZ,
- rotation, rotationX, rotationY, scaleX, scaleY);
- }
-
- /**
* Sets the pivot value for the display list on the X axis
*
* @param pivotX The pivot value of the display list on the X axis, in pixels
@@ -668,6 +668,10 @@
return nGetPivotY(mNativeDisplayList);
}
+ public boolean isPivotExplicitlySet() {
+ return nIsPivotExplicitlySet(mNativeDisplayList);
+ }
+
/**
* Sets the camera distance for the display list. Refer to
* {@link View#setCameraDistance(float)} for more information on how to
@@ -834,6 +838,12 @@
private static native void nDestroyDisplayList(long displayList);
private static native void nSetDisplayListName(long displayList, String name);
+ // Matrix
+
+ private static native void nGetTransformMatrix(long displayList, long nativeMatrix);
+ private static native void nGetInverseTransformMatrix(long displayList, long nativeMatrix);
+ private static native boolean nHasIdentityMatrix(long displayList);
+
// Properties
private static native void nOffsetTopAndBottom(long displayList, float offset);
@@ -856,6 +866,8 @@
private static native void nSetOutlineConvexPath(long displayList, long nativePath);
private static native void nSetOutlineEmpty(long displayList);
private static native void nSetClipToOutline(long displayList, boolean clipToOutline);
+ private static native void nSetRevealClip(long displayList,
+ boolean shouldClip, boolean inverseClip, float x, float y, float radius);
private static native void nSetAlpha(long displayList, float alpha);
private static native void nSetHasOverlappingRendering(long displayList,
boolean hasOverlappingRendering);
@@ -867,9 +879,6 @@
private static native void nSetRotationY(long displayList, float rotationY);
private static native void nSetScaleX(long displayList, float scaleX);
private static native void nSetScaleY(long displayList, float scaleY);
- private static native void nSetTransformationInfo(long displayList, float alpha,
- float translationX, float translationY, float translationZ,
- float rotation, float rotationX, float rotationY, float scaleX, float scaleY);
private static native void nSetStaticMatrix(long displayList, long nativeMatrix);
private static native void nSetAnimationMatrix(long displayList, long animationMatrix);
@@ -888,6 +897,7 @@
private static native float nGetRotation(long displayList);
private static native float nGetRotationX(long displayList);
private static native float nGetRotationY(long displayList);
+ private static native boolean nIsPivotExplicitlySet(long displayList);
private static native float nGetPivotX(long displayList);
private static native float nGetPivotY(long displayList);
private static native void nOutput(long displayList);
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 2a488a0..7b8a1ff 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -186,6 +186,11 @@
}
@Override
+ public void invokeFunctor(long functor, boolean waitForCompletion) {
+ nInvokeFunctor(mNativeProxy, functor, waitForCompletion);
+ }
+
+ @Override
HardwareLayer createDisplayListLayer(int width, int height) {
long layer = nCreateDisplayListLayer(mNativeProxy, width, height);
return HardwareLayer.adoptDisplayListLayer(this, layer);
@@ -266,6 +271,7 @@
private static native void nAttachFunctor(long nativeProxy, long functor);
private static native void nDetachFunctor(long nativeProxy, long functor);
+ private static native void nInvokeFunctor(long nativeProxy, long functor, boolean waitForCompletion);
private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
private static native long nCreateTextureLayer(long nativeProxy);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 5e512b6..6c414f6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16,6 +16,8 @@
package android.view;
+import android.animation.RevealAnimator;
+import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -33,7 +35,6 @@
import android.graphics.Matrix;
import android.graphics.Outline;
import android.graphics.Paint;
-import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
@@ -1791,12 +1792,9 @@
private static final int PFLAG_HOVERED = 0x10000000;
/**
- * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
- * for transform operations
- *
- * @hide
+ * no longer needed, should be reused
*/
- private static final int PFLAG_PIVOT_EXPLICITLY_SET = 0x20000000;
+ private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
/** {@hide} */
static final int PFLAG_ACTIVATED = 0x40000000;
@@ -2929,123 +2927,23 @@
static class TransformationInfo {
/**
* The transform matrix for the View. This transform is calculated internally
- * based on the rotation, scaleX, and scaleY properties. The identity matrix
- * is used by default. Do *not* use this variable directly; instead call
- * getMatrix(), which will automatically recalculate the matrix if necessary
- * to get the correct matrix based on the latest rotation and scale properties.
+ * based on the translation, rotation, and scale properties.
+ *
+ * Do *not* use this variable directly; instead call getMatrix(), which will
+ * load the value from the View's RenderNode.
*/
private final Matrix mMatrix = new Matrix();
/**
- * The transform matrix for the View. This transform is calculated internally
- * based on the rotation, scaleX, and scaleY properties. The identity matrix
- * is used by default. Do *not* use this variable directly; instead call
- * getInverseMatrix(), which will automatically recalculate the matrix if necessary
- * to get the correct matrix based on the latest rotation and scale properties.
+ * The inverse transform matrix for the View. This transform is calculated
+ * internally based on the translation, rotation, and scale properties.
+ *
+ * Do *not* use this variable directly; instead call getInverseMatrix(),
+ * which will load the value from the View's RenderNode.
*/
private Matrix mInverseMatrix;
/**
- * An internal variable that tracks whether we need to recalculate the
- * transform matrix, based on whether the rotation or scaleX/Y properties
- * have changed since the matrix was last calculated.
- */
- boolean mMatrixDirty = false;
-
- /**
- * An internal variable that tracks whether we need to recalculate the
- * transform matrix, based on whether the rotation or scaleX/Y properties
- * have changed since the matrix was last calculated.
- */
- private boolean mInverseMatrixDirty = true;
-
- /**
- * A variable that tracks whether we need to recalculate the
- * transform matrix, based on whether the rotation or scaleX/Y properties
- * have changed since the matrix was last calculated. This variable
- * is only valid after a call to updateMatrix() or to a function that
- * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix().
- */
- private boolean mMatrixIsIdentity = true;
-
- /**
- * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set.
- */
- private Camera mCamera = null;
-
- /**
- * This matrix is used when computing the matrix for 3D rotations.
- */
- private Matrix matrix3D = null;
-
- /**
- * These prev values are used to recalculate a centered pivot point when necessary. The
- * pivot point is only used in matrix operations (when rotation, scale, or translation are
- * set), so thes values are only used then as well.
- */
- private int mPrevWidth = -1;
- private int mPrevHeight = -1;
-
- /**
- * The degrees rotation around the vertical axis through the pivot point.
- */
- @ViewDebug.ExportedProperty
- float mRotationY = 0f;
-
- /**
- * The degrees rotation around the horizontal axis through the pivot point.
- */
- @ViewDebug.ExportedProperty
- float mRotationX = 0f;
-
- /**
- * The degrees rotation around the pivot point.
- */
- @ViewDebug.ExportedProperty
- float mRotation = 0f;
-
- /**
- * The amount of translation of the object away from its left property (post-layout).
- */
- @ViewDebug.ExportedProperty
- float mTranslationX = 0f;
-
- /**
- * The amount of translation of the object away from its top property (post-layout).
- */
- @ViewDebug.ExportedProperty
- float mTranslationY = 0f;
-
- @ViewDebug.ExportedProperty
- float mTranslationZ = 0f;
-
- /**
- * The amount of scale in the x direction around the pivot point. A
- * value of 1 means no scaling is applied.
- */
- @ViewDebug.ExportedProperty
- float mScaleX = 1f;
-
- /**
- * The amount of scale in the y direction around the pivot point. A
- * value of 1 means no scaling is applied.
- */
- @ViewDebug.ExportedProperty
- float mScaleY = 1f;
-
- /**
- * The x location of the point around which the view is rotated and scaled.
- */
- @ViewDebug.ExportedProperty
- float mPivotX = 0f;
-
- /**
- * The y location of the point around which the view is rotated and scaled.
- */
- @ViewDebug.ExportedProperty
- float mPivotY = 0f;
-
- /**
* The opacity of the View. This is a value from 0 to 1, where 0 means
* completely transparent and 1 means completely opaque.
*/
@@ -3550,13 +3448,13 @@
private Bitmap mUnscaledDrawingCache;
/**
- * Display list used for the View content.
+ * RenderNode holding View properties, potentially holding a DisplayList of View content.
* <p>
* When non-null and valid, this is expected to contain an up-to-date copy
- * of the View content. It is cleared on temporary detach and reset on
+ * of the View content. Its DisplayList content is cleared on temporary detach and reset on
* cleanup.
*/
- RenderNode mDisplayList;
+ final RenderNode mRenderNode;
/**
* Set to true when the view is sending hover accessibility events because it
@@ -3607,6 +3505,7 @@
setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
mUserPaddingStart = UNDEFINED_PADDING;
mUserPaddingEnd = UNDEFINED_PADDING;
+ mRenderNode = RenderNode.create(getClass().getName());
if (!sCompatibilityDone && context != null) {
final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
@@ -4171,6 +4070,7 @@
*/
View() {
mResources = null;
+ mRenderNode = RenderNode.create(getClass().getName());
}
public String toString() {
@@ -4846,10 +4746,10 @@
final float x = r.exactCenterX();
final float y = r.exactCenterY();
- mBackground.setHotspot(Drawable.HOTSPOT_FOCUS, x, y);
+ mBackground.setHotspot(R.attr.state_focused, x, y);
if (!focused) {
- mBackground.removeHotspot(Drawable.HOTSPOT_FOCUS);
+ mBackground.removeHotspot(R.attr.state_focused);
}
}
}
@@ -5726,7 +5626,8 @@
* @hide
*/
public int getAccessibilityWindowId() {
- return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId : NO_ID;
+ return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
+ : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
}
/**
@@ -9016,10 +8917,13 @@
* @return True if the event was handled, false otherwise.
*/
public boolean onTouchEvent(MotionEvent event) {
+ final float x = event.getX();
+ final float y = event.getY();
final int viewFlags = mViewFlags;
if ((viewFlags & ENABLED_MASK) == DISABLED) {
if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
+ clearHotspot(R.attr.state_pressed);
setPressed(false);
}
// A disabled view that is clickable still consumes the touch
@@ -9052,6 +8956,7 @@
// showed it as pressed. Make it show the pressed
// state now (before scheduling the click) to ensure
// the user sees it.
+ setHotspot(R.attr.state_pressed, x, y);
setPressed(true);
}
@@ -9084,7 +8989,10 @@
// If the post failed, unpress right now
mUnsetPressedState.run();
}
+
removeTapCallback();
+ } else {
+ clearHotspot(R.attr.state_pressed);
}
break;
@@ -9105,23 +9013,26 @@
if (mPendingCheckForTap == null) {
mPendingCheckForTap = new CheckForTap();
}
+ mPendingCheckForTap.x = event.getX();
+ mPendingCheckForTap.y = event.getY();
postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
} else {
// Not inside a scrolling container, so show the feedback right away
+ setHotspot(R.attr.state_pressed, x, y);
setPressed(true);
checkForLongClick(0);
}
break;
case MotionEvent.ACTION_CANCEL:
+ clearHotspot(R.attr.state_pressed);
setPressed(false);
removeTapCallback();
removeLongPressCallback();
break;
case MotionEvent.ACTION_MOVE:
- final int x = (int) event.getX();
- final int y = (int) event.getY();
+ setHotspot(R.attr.state_pressed, x, y);
// Be lenient about moving outside of buttons
if (!pointInView(x, y, mTouchSlop)) {
@@ -9137,46 +9048,24 @@
break;
}
- if (mBackground != null && mBackground.supportsHotspots()) {
- manageTouchHotspot(event);
- }
-
return true;
}
return false;
}
- private void manageTouchHotspot(MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- case MotionEvent.ACTION_POINTER_DOWN: {
- final int index = event.getActionIndex();
- setPointerHotspot(event, index);
- } break;
- case MotionEvent.ACTION_MOVE: {
- final int count = event.getPointerCount();
- for (int index = 0; index < count; index++) {
- setPointerHotspot(event, index);
- }
- } break;
- case MotionEvent.ACTION_POINTER_UP: {
- final int actionIndex = event.getActionIndex();
- final int pointerId = event.getPointerId(actionIndex);
- mBackground.removeHotspot(pointerId);
- } break;
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- mBackground.clearHotspots();
- break;
+ private void setHotspot(int id, float x, float y) {
+ final Drawable bg = mBackground;
+ if (bg != null && bg.supportsHotspots()) {
+ bg.setHotspot(id, x, y);
}
}
- private void setPointerHotspot(MotionEvent event, int index) {
- final int id = event.getPointerId(index);
- final float x = event.getX(index);
- final float y = event.getY(index);
- mBackground.setHotspot(id, x, y);
+ private void clearHotspot(int id) {
+ final Drawable bg = mBackground;
+ if (bg != null && bg.supportsHotspots()) {
+ bg.removeHotspot(id);
+ }
}
/**
@@ -9216,6 +9105,7 @@
*/
private void removeUnsetPressCallback() {
if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
+ clearHotspot(R.attr.state_pressed);
setPressed(false);
removeCallbacks(mUnsetPressedState);
}
@@ -9694,21 +9584,10 @@
* @return The current transform matrix for the view
*/
public Matrix getMatrix() {
- if (mTransformationInfo != null) {
- updateMatrix();
- return mTransformationInfo.mMatrix;
- }
- return Matrix.IDENTITY_MATRIX;
- }
-
- /**
- * Utility function to determine if the value is far enough away from zero to be
- * considered non-zero.
- * @param value A floating point value to check for zero-ness
- * @return whether the passed-in value is far enough away from zero to be considered non-zero
- */
- private static boolean nonzero(float value) {
- return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON);
+ ensureTransformationInfo();
+ final Matrix matrix = mTransformationInfo.mMatrix;
+ mRenderNode.getMatrix(matrix);
+ return matrix;
}
/**
@@ -9718,11 +9597,7 @@
* @return True if the transform matrix is the identity matrix, false otherwise.
*/
final boolean hasIdentityMatrix() {
- if (mTransformationInfo != null) {
- updateMatrix();
- return mTransformationInfo.mMatrixIsIdentity;
- }
- return true;
+ return mRenderNode.hasIdentityMatrix();
}
void ensureTransformationInfo() {
@@ -9731,53 +9606,6 @@
}
}
- /**
- * Recomputes the transform matrix if necessary.
- */
- private void updateMatrix() {
- final TransformationInfo info = mTransformationInfo;
- if (info == null) {
- return;
- }
- if (info.mMatrixDirty) {
- // transform-related properties have changed since the last time someone
- // asked for the matrix; recalculate it with the current values
-
- // Figure out if we need to update the pivot point
- if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
- if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
- info.mPrevWidth = mRight - mLeft;
- info.mPrevHeight = mBottom - mTop;
- info.mPivotX = info.mPrevWidth / 2f;
- info.mPivotY = info.mPrevHeight / 2f;
- }
- }
- info.mMatrix.reset();
- if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) {
- info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY);
- info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY);
- info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
- } else {
- if (info.mCamera == null) {
- info.mCamera = new Camera();
- info.matrix3D = new Matrix();
- }
- info.mCamera.save();
- info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
- info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation);
- info.mCamera.getMatrix(info.matrix3D);
- info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY);
- info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX,
- info.mPivotY + info.mTranslationY);
- info.mMatrix.postConcat(info.matrix3D);
- info.mCamera.restore();
- }
- info.mMatrixDirty = false;
- info.mMatrixIsIdentity = info.mMatrix.isIdentity();
- info.mInverseMatrixDirty = true;
- }
- }
-
/**
* Utility method to retrieve the inverse of the current mMatrix property.
* We cache the matrix to avoid recalculating it when transform properties
@@ -9786,19 +9614,13 @@
* @return The inverse of the current matrix of this view.
*/
final Matrix getInverseMatrix() {
- final TransformationInfo info = mTransformationInfo;
- if (info != null) {
- updateMatrix();
- if (info.mInverseMatrixDirty) {
- if (info.mInverseMatrix == null) {
- info.mInverseMatrix = new Matrix();
- }
- info.mMatrix.invert(info.mInverseMatrix);
- info.mInverseMatrixDirty = false;
- }
- return info.mInverseMatrix;
+ ensureTransformationInfo();
+ if (mTransformationInfo.mInverseMatrix == null) {
+ mTransformationInfo.mInverseMatrix = new Matrix();
}
- return Matrix.IDENTITY_MATRIX;
+ final Matrix matrix = mTransformationInfo.mInverseMatrix;
+ mRenderNode.getInverseMatrix(matrix);
+ return matrix;
}
/**
@@ -9809,14 +9631,8 @@
* @return The distance along the Z axis.
*/
public float getCameraDistance() {
- ensureTransformationInfo();
final float dpi = mResources.getDisplayMetrics().densityDpi;
- final TransformationInfo info = mTransformationInfo;
- if (info.mCamera == null) {
- info.mCamera = new Camera();
- info.matrix3D = new Matrix();
- }
- return -(info.mCamera.getLocationZ() * dpi);
+ return -(mRenderNode.getCameraDistance() * dpi);
}
/**
@@ -9859,27 +9675,13 @@
* @see #setRotationY(float)
*/
public void setCameraDistance(float distance) {
- invalidateViewProperty(true, false);
-
- ensureTransformationInfo();
final float dpi = mResources.getDisplayMetrics().densityDpi;
- final TransformationInfo info = mTransformationInfo;
- if (info.mCamera == null) {
- info.mCamera = new Camera();
- info.matrix3D = new Matrix();
- }
- info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi);
- info.mMatrixDirty = true;
-
+ invalidateViewProperty(true, false);
+ mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
invalidateViewProperty(false, false);
- if (mDisplayList != null) {
- mDisplayList.setCameraDistance(-Math.abs(distance) / dpi);
- }
- if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
- // View was rejected last time it was drawn by its parent; this may have changed
- invalidateParentIfNeeded();
- }
+
+ invalidateParentIfNeededAndWasQuickRejected();
}
/**
@@ -9893,7 +9695,7 @@
*/
@ViewDebug.ExportedProperty(category = "drawing")
public float getRotation() {
- return mTransformationInfo != null ? mTransformationInfo.mRotation : 0;
+ return mRenderNode.getRotation();
}
/**
@@ -9911,21 +9713,13 @@
* @attr ref android.R.styleable#View_rotation
*/
public void setRotation(float rotation) {
- ensureTransformationInfo();
- final TransformationInfo info = mTransformationInfo;
- if (info.mRotation != rotation) {
+ if (rotation != getRotation()) {
// Double-invalidation is necessary to capture view's old and new areas
invalidateViewProperty(true, false);
- info.mRotation = rotation;
- info.mMatrixDirty = true;
+ mRenderNode.setRotation(rotation);
invalidateViewProperty(false, true);
- if (mDisplayList != null) {
- mDisplayList.setRotation(rotation);
- }
- if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
- // View was rejected last time it was drawn by its parent; this may have changed
- invalidateParentIfNeeded();
- }
+
+ invalidateParentIfNeededAndWasQuickRejected();
}
}
@@ -9940,7 +9734,7 @@
*/
@ViewDebug.ExportedProperty(category = "drawing")
public float getRotationY() {
- return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
+ return mRenderNode.getRotationY();
}
/**
@@ -9963,20 +9757,12 @@
* @attr ref android.R.styleable#View_rotationY
*/
public void setRotationY(float rotationY) {
- ensureTransformationInfo();
- final TransformationInfo info = mTransformationInfo;
- if (info.mRotationY != rotationY) {
+ if (rotationY != getRotationY()) {
invalidateViewProperty(true, false);
- info.mRotationY = rotationY;
- info.mMatrixDirty = true;
+ mRenderNode.setRotationY(rotationY);
invalidateViewProperty(false, true);
- if (mDisplayList != null) {
- mDisplayList.setRotationY(rotationY);
- }
- if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
- // View was rejected last time it was drawn by its parent; this may have changed
- invalidateParentIfNeeded();
- }
+
+ invalidateParentIfNeededAndWasQuickRejected();
}
}
@@ -9991,7 +9777,7 @@
*/
@ViewDebug.ExportedProperty(category = "drawing")
public float getRotationX() {
- return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0;
+ return mRenderNode.getRotationX();
}
/**
@@ -10014,20 +9800,12 @@
* @attr ref android.R.styleable#View_rotationX
*/
public void setRotationX(float rotationX) {
- ensureTransformationInfo();
- final TransformationInfo info = mTransformationInfo;
- if (info.mRotationX != rotationX) {
+ if (rotationX != getRotationX()) {
invalidateViewProperty(true, false);
- info.mRotationX = rotationX;
- info.mMatrixDirty = true;
+ mRenderNode.setRotationX(rotationX);
invalidateViewProperty(false, true);
- if (mDisplayList != null) {
- mDisplayList.setRotationX(rotationX);
- }
- if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
- // View was rejected last time it was drawn by its parent; this may have changed
- invalidateParentIfNeeded();
- }
+
+ invalidateParentIfNeededAndWasQuickRejected();
}
}
@@ -10043,7 +9821,7 @@
*/
@ViewDebug.ExportedProperty(category = "drawing")
public float getScaleX() {
- return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1;
+ return mRenderNode.getScaleX();
}
/**
@@ -10057,20 +9835,12 @@
* @attr ref android.R.styleable#View_scaleX
*/
public void setScaleX(float scaleX) {
- ensureTransformationInfo();
- final TransformationInfo info = mTransformationInfo;
- if (info.mScaleX != scaleX) {
+ if (scaleX != getScaleX()) {
invalidateViewProperty(true, false);
- info.mScaleX = scaleX;
- info.mMatrixDirty = true;
+ mRenderNode.setScaleX(scaleX);
invalidateViewProperty(false, true);
- if (mDisplayList != null) {
- mDisplayList.setScaleX(scaleX);
- }
- if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
- // View was rejected last time it was drawn by its parent; this may have changed
- invalidateParentIfNeeded();
- }
+
+ invalidateParentIfNeededAndWasQuickRejected();
}
}
@@ -10086,7 +9856,7 @@
*/
@ViewDebug.ExportedProperty(category = "drawing")
public float getScaleY() {
- return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1;
+ return mRenderNode.getScaleY();
}
/**
@@ -10100,20 +9870,12 @@
* @attr ref android.R.styleable#View_scaleY
*/
public void setScaleY(float scaleY) {
- ensureTransformationInfo();
- final TransformationInfo info = mTransformationInfo;
- if (info.mScaleY != scaleY) {
+ if (scaleY != getScaleY()) {
invalidateViewProperty(true, false);
- info.mScaleY = scaleY;
- info.mMatrixDirty = true;
+ mRenderNode.setScaleY(scaleY);
invalidateViewProperty(false, true);
- if (mDisplayList != null) {
- mDisplayList.setScaleY(scaleY);
- }
- if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
- // View was rejected last time it was drawn by its parent; this may have changed
- invalidateParentIfNeeded();
- }
+
+ invalidateParentIfNeededAndWasQuickRejected();
}
}
@@ -10131,7 +9893,7 @@
*/
@ViewDebug.ExportedProperty(category = "drawing")
public float getPivotX() {
- return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0;
+ return mRenderNode.getPivotX();
}
/**
@@ -10150,23 +9912,12 @@
* @attr ref android.R.styleable#View_transformPivotX
*/
public void setPivotX(float pivotX) {
- ensureTransformationInfo();
- final TransformationInfo info = mTransformationInfo;
- boolean pivotSet = (mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) ==
- PFLAG_PIVOT_EXPLICITLY_SET;
- if (info.mPivotX != pivotX || !pivotSet) {
- mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
+ if (mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
invalidateViewProperty(true, false);
- info.mPivotX = pivotX;
- info.mMatrixDirty = true;
+ mRenderNode.setPivotX(pivotX);
invalidateViewProperty(false, true);
- if (mDisplayList != null) {
- mDisplayList.setPivotX(pivotX);
- }
- if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
- // View was rejected last time it was drawn by its parent; this may have changed
- invalidateParentIfNeeded();
- }
+
+ invalidateParentIfNeededAndWasQuickRejected();
}
}
@@ -10184,7 +9935,7 @@
*/
@ViewDebug.ExportedProperty(category = "drawing")
public float getPivotY() {
- return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0;
+ return mRenderNode.getPivotY();
}
/**
@@ -10202,23 +9953,12 @@
* @attr ref android.R.styleable#View_transformPivotY
*/
public void setPivotY(float pivotY) {
- ensureTransformationInfo();
- final TransformationInfo info = mTransformationInfo;
- boolean pivotSet = (mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) ==
- PFLAG_PIVOT_EXPLICITLY_SET;
- if (info.mPivotY != pivotY || !pivotSet) {
- mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
+ if (mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
invalidateViewProperty(true, false);
- info.mPivotY = pivotY;
- info.mMatrixDirty = true;
+ mRenderNode.setPivotY(pivotY);
invalidateViewProperty(false, true);
- if (mDisplayList != null) {
- mDisplayList.setPivotY(pivotY);
- }
- if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
- // View was rejected last time it was drawn by its parent; this may have changed
- invalidateParentIfNeeded();
- }
+
+ invalidateParentIfNeededAndWasQuickRejected();
}
}
@@ -10296,9 +10036,7 @@
} else {
mPrivateFlags &= ~PFLAG_ALPHA_SET;
invalidateViewProperty(true, false);
- if (mDisplayList != null) {
- mDisplayList.setAlpha(getFinalAlpha());
- }
+ mRenderNode.setAlpha(getFinalAlpha());
}
}
}
@@ -10323,9 +10061,7 @@
return true;
} else {
mPrivateFlags &= ~PFLAG_ALPHA_SET;
- if (mDisplayList != null) {
- mDisplayList.setAlpha(getFinalAlpha());
- }
+ mRenderNode.setAlpha(getFinalAlpha());
}
}
return false;
@@ -10346,9 +10082,7 @@
mTransformationInfo.mTransitionAlpha = alpha;
mPrivateFlags &= ~PFLAG_ALPHA_SET;
invalidateViewProperty(true, false);
- if (mDisplayList != null) {
- mDisplayList.setAlpha(getFinalAlpha());
- }
+ mRenderNode.setAlpha(getFinalAlpha());
}
}
@@ -10395,9 +10129,7 @@
*/
public final void setTop(int top) {
if (top != mTop) {
- updateMatrix();
- final boolean matrixIsIdentity = mTransformationInfo == null
- || mTransformationInfo.mMatrixIsIdentity;
+ final boolean matrixIsIdentity = hasIdentityMatrix();
if (matrixIsIdentity) {
if (mAttachInfo != null) {
int minTop;
@@ -10420,17 +10152,11 @@
int oldHeight = mBottom - mTop;
mTop = top;
- if (mDisplayList != null) {
- mDisplayList.setTop(mTop);
- }
+ mRenderNode.setTop(mTop);
sizeChange(width, mBottom - mTop, width, oldHeight);
if (!matrixIsIdentity) {
- if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
- // A change in dimension means an auto-centered pivot point changes, too
- mTransformationInfo.mMatrixDirty = true;
- }
mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
invalidate(true);
}
@@ -10471,9 +10197,7 @@
*/
public final void setBottom(int bottom) {
if (bottom != mBottom) {
- updateMatrix();
- final boolean matrixIsIdentity = mTransformationInfo == null
- || mTransformationInfo.mMatrixIsIdentity;
+ final boolean matrixIsIdentity = hasIdentityMatrix();
if (matrixIsIdentity) {
if (mAttachInfo != null) {
int maxBottom;
@@ -10493,17 +10217,11 @@
int oldHeight = mBottom - mTop;
mBottom = bottom;
- if (mDisplayList != null) {
- mDisplayList.setBottom(mBottom);
- }
+ mRenderNode.setBottom(mBottom);
sizeChange(width, mBottom - mTop, width, oldHeight);
if (!matrixIsIdentity) {
- if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
- // A change in dimension means an auto-centered pivot point changes, too
- mTransformationInfo.mMatrixDirty = true;
- }
mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
invalidate(true);
}
@@ -10535,9 +10253,7 @@
*/
public final void setLeft(int left) {
if (left != mLeft) {
- updateMatrix();
- final boolean matrixIsIdentity = mTransformationInfo == null
- || mTransformationInfo.mMatrixIsIdentity;
+ final boolean matrixIsIdentity = hasIdentityMatrix();
if (matrixIsIdentity) {
if (mAttachInfo != null) {
int minLeft;
@@ -10560,17 +10276,11 @@
int height = mBottom - mTop;
mLeft = left;
- if (mDisplayList != null) {
- mDisplayList.setLeft(left);
- }
+ mRenderNode.setLeft(left);
sizeChange(mRight - mLeft, height, oldWidth, height);
if (!matrixIsIdentity) {
- if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
- // A change in dimension means an auto-centered pivot point changes, too
- mTransformationInfo.mMatrixDirty = true;
- }
mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
invalidate(true);
}
@@ -10602,9 +10312,7 @@
*/
public final void setRight(int right) {
if (right != mRight) {
- updateMatrix();
- final boolean matrixIsIdentity = mTransformationInfo == null
- || mTransformationInfo.mMatrixIsIdentity;
+ final boolean matrixIsIdentity = hasIdentityMatrix();
if (matrixIsIdentity) {
if (mAttachInfo != null) {
int maxRight;
@@ -10624,17 +10332,11 @@
int height = mBottom - mTop;
mRight = right;
- if (mDisplayList != null) {
- mDisplayList.setRight(mRight);
- }
+ mRenderNode.setRight(mRight);
sizeChange(mRight - mLeft, height, oldWidth, height);
if (!matrixIsIdentity) {
- if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
- // A change in dimension means an auto-centered pivot point changes, too
- mTransformationInfo.mMatrixDirty = true;
- }
mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
invalidate(true);
}
@@ -10656,7 +10358,7 @@
*/
@ViewDebug.ExportedProperty(category = "drawing")
public float getX() {
- return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
+ return mLeft + getTranslationX();
}
/**
@@ -10679,7 +10381,7 @@
*/
@ViewDebug.ExportedProperty(category = "drawing")
public float getY() {
- return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
+ return mTop + getTranslationY();
}
/**
@@ -10703,7 +10405,7 @@
*/
@ViewDebug.ExportedProperty(category = "drawing")
public float getTranslationX() {
- return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
+ return mRenderNode.getTranslationX();
}
/**
@@ -10717,21 +10419,12 @@
* @attr ref android.R.styleable#View_translationX
*/
public void setTranslationX(float translationX) {
- ensureTransformationInfo();
- final TransformationInfo info = mTransformationInfo;
- if (info.mTranslationX != translationX) {
- // Double-invalidation is necessary to capture view's old and new areas
+ if (translationX != getTranslationX()) {
invalidateViewProperty(true, false);
- info.mTranslationX = translationX;
- info.mMatrixDirty = true;
+ mRenderNode.setTranslationX(translationX);
invalidateViewProperty(false, true);
- if (mDisplayList != null) {
- mDisplayList.setTranslationX(translationX);
- }
- if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
- // View was rejected last time it was drawn by its parent; this may have changed
- invalidateParentIfNeeded();
- }
+
+ invalidateParentIfNeededAndWasQuickRejected();
}
}
@@ -10745,7 +10438,7 @@
*/
@ViewDebug.ExportedProperty(category = "drawing")
public float getTranslationY() {
- return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
+ return mRenderNode.getTranslationY();
}
/**
@@ -10759,20 +10452,12 @@
* @attr ref android.R.styleable#View_translationY
*/
public void setTranslationY(float translationY) {
- ensureTransformationInfo();
- final TransformationInfo info = mTransformationInfo;
- if (info.mTranslationY != translationY) {
+ if (translationY != getTranslationY()) {
invalidateViewProperty(true, false);
- info.mTranslationY = translationY;
- info.mMatrixDirty = true;
+ mRenderNode.setTranslationY(translationY);
invalidateViewProperty(false, true);
- if (mDisplayList != null) {
- mDisplayList.setTranslationY(translationY);
- }
- if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
- // View was rejected last time it was drawn by its parent; this may have changed
- invalidateParentIfNeeded();
- }
+
+ invalidateParentIfNeededAndWasQuickRejected();
}
}
@@ -10783,7 +10468,7 @@
*/
@ViewDebug.ExportedProperty(category = "drawing")
public float getTranslationZ() {
- return mTransformationInfo != null ? mTransformationInfo.mTranslationZ : 0;
+ return mRenderNode.getTranslationZ();
}
/**
@@ -10792,24 +10477,53 @@
* @attr ref android.R.styleable#View_translationZ
*/
public void setTranslationZ(float translationZ) {
- ensureTransformationInfo();
- final TransformationInfo info = mTransformationInfo;
- if (info.mTranslationZ != translationZ) {
+ if (translationZ != getTranslationZ()) {
invalidateViewProperty(true, false);
- info.mTranslationZ = translationZ;
- info.mMatrixDirty = true;
+ mRenderNode.setTranslationZ(translationZ);
invalidateViewProperty(false, true);
- if (mDisplayList != null) {
- mDisplayList.setTranslationZ(translationZ);
- }
- if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
- // View was rejected last time it was drawn by its parent; this may have changed
- invalidateParentIfNeeded();
- }
+
+ invalidateParentIfNeededAndWasQuickRejected();
}
}
/**
+ * Returns a ValueAnimator which can animate a clipping circle.
+ * <p>
+ * The View will be clipped to the animating circle.
+ * <p>
+ * Any shadow cast by the View will respect the circular clip from this animator.
+ *
+ * @param centerX The x coordinate of the center of the animating circle.
+ * @param centerY The y coordinate of the center of the animating circle.
+ * @param startRadius The starting radius of the animating circle.
+ * @param endRadius The ending radius of the animating circle.
+ */
+ public final ValueAnimator createRevealAnimator(int centerX, int centerY,
+ float startRadius, float endRadius) {
+ return RevealAnimator.ofRevealCircle(this, centerX, centerY,
+ startRadius, endRadius, false);
+ }
+
+ /**
+ * Returns a ValueAnimator which can animate a clearing circle.
+ * <p>
+ * The View is prevented from drawing within the circle, so the content
+ * behind the View shows through.
+ *
+ * @param centerX The x coordinate of the center of the animating circle.
+ * @param centerY The y coordinate of the center of the animating circle.
+ * @param startRadius The starting radius of the animating circle.
+ * @param endRadius The ending radius of the animating circle.
+ *
+ * @hide
+ */
+ public final ValueAnimator createClearCircleAnimator(int centerX, int centerY,
+ float startRadius, float endRadius) {
+ return RevealAnimator.ofRevealCircle(this, centerX, centerY,
+ startRadius, endRadius, true);
+ }
+
+ /**
* Sets the outline of the view, which defines the shape of the shadow it
* casts, and can used for clipping.
* <p>
@@ -10838,10 +10552,7 @@
}
mOutline.set(outline);
}
-
- if (mDisplayList != null) {
- mDisplayList.setOutline(mOutline);
- }
+ mRenderNode.setOutline(mOutline);
}
/**
@@ -10876,26 +10587,34 @@
} else {
mPrivateFlags3 &= ~PFLAG3_CLIP_TO_OUTLINE;
}
- if (mDisplayList != null) {
- mDisplayList.setClipToOutline(clipToOutline);
- }
+ mRenderNode.setClipToOutline(clipToOutline);
}
}
/**
+ * Private API to be used for reveal animation
+ *
+ * @hide
+ */
+ public void setRevealClip(boolean shouldClip, boolean inverseClip,
+ float x, float y, float radius) {
+ mRenderNode.setRevealClip(shouldClip, inverseClip, x, y, radius);
+ // TODO: Handle this invalidate in a better way, or purely in native.
+ invalidate();
+ }
+
+ /**
* Hit rectangle in parent's coordinates
*
* @param outRect The hit rectangle of the view.
*/
public void getHitRect(Rect outRect) {
- updateMatrix();
- final TransformationInfo info = mTransformationInfo;
- if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) {
+ if (hasIdentityMatrix() || mAttachInfo == null) {
outRect.set(mLeft, mTop, mRight, mBottom);
} else {
final RectF tmpRect = mAttachInfo.mTmpTransformRect;
tmpRect.set(0, 0, getWidth(), getHeight());
- info.mMatrix.mapRect(tmpRect);
+ getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
(int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
}
@@ -10984,11 +10703,9 @@
*/
public void offsetTopAndBottom(int offset) {
if (offset != 0) {
- updateMatrix();
- final boolean matrixIsIdentity = mTransformationInfo == null
- || mTransformationInfo.mMatrixIsIdentity;
+ final boolean matrixIsIdentity = hasIdentityMatrix();
if (matrixIsIdentity) {
- if (mDisplayList != null) {
+ if (isHardwareAccelerated()) {
invalidateViewProperty(false, false);
} else {
final ViewParent p = mParent;
@@ -11016,8 +10733,8 @@
mTop += offset;
mBottom += offset;
- if (mDisplayList != null) {
- mDisplayList.offsetTopAndBottom(offset);
+ mRenderNode.offsetTopAndBottom(offset);
+ if (isHardwareAccelerated()) {
invalidateViewProperty(false, false);
} else {
if (!matrixIsIdentity) {
@@ -11035,11 +10752,9 @@
*/
public void offsetLeftAndRight(int offset) {
if (offset != 0) {
- updateMatrix();
- final boolean matrixIsIdentity = mTransformationInfo == null
- || mTransformationInfo.mMatrixIsIdentity;
+ final boolean matrixIsIdentity = hasIdentityMatrix();
if (matrixIsIdentity) {
- if (mDisplayList != null) {
+ if (isHardwareAccelerated()) {
invalidateViewProperty(false, false);
} else {
final ViewParent p = mParent;
@@ -11064,8 +10779,8 @@
mLeft += offset;
mRight += offset;
- if (mDisplayList != null) {
- mDisplayList.offsetLeftAndRight(offset);
+ mRenderNode.offsetLeftAndRight(offset);
+ if (isHardwareAccelerated()) {
invalidateViewProperty(false, false);
} else {
if (!matrixIsIdentity) {
@@ -11445,7 +11160,7 @@
}
// Damage the entire IsolatedZVolume recieving this view's shadow.
- if (getTranslationZ() != 0) {
+ if (isHardwareAccelerated() && getTranslationZ() != 0) {
damageShadowReceiver();
}
}
@@ -11508,7 +11223,9 @@
* list properties are not being used in this view
*/
void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
- if (mDisplayList == null || (mPrivateFlags & PFLAG_DRAW_ANIMATION) == PFLAG_DRAW_ANIMATION) {
+ if (!isHardwareAccelerated()
+ || !mRenderNode.isValid()
+ || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
if (invalidateParent) {
invalidateParentCaches();
}
@@ -11519,7 +11236,7 @@
} else {
damageInParent();
}
- if (invalidateParent && getTranslationZ() != 0) {
+ if (isHardwareAccelerated() && invalidateParent && getTranslationZ() != 0) {
damageShadowReceiver();
}
}
@@ -11536,7 +11253,7 @@
final Rect r = ai.mTmpInvalRect;
r.set(0, 0, mRight - mLeft, mBottom - mTop);
if (mParent instanceof ViewGroup) {
- ((ViewGroup) mParent).invalidateChildFast(this, r);
+ ((ViewGroup) mParent).damageChild(this, r);
} else {
mParent.invalidateChild(this, r);
}
@@ -11589,6 +11306,16 @@
}
/**
+ * @hide
+ */
+ protected void invalidateParentIfNeededAndWasQuickRejected() {
+ if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
+ // View was rejected last time it was drawn by its parent; this may have changed
+ invalidateParentIfNeeded();
+ }
+ }
+
+ /**
* Indicates whether this View is opaque. An opaque View guarantees that it will
* draw all the pixels overlapping its bounds using a fully opaque color.
*
@@ -13675,10 +13402,7 @@
mHardwareLayer.setLayerPaint(mLayerPaint);
RenderNode displayList = mHardwareLayer.startRecording();
- if (getDisplayList(displayList, true) != displayList) {
- throw new IllegalStateException("getDisplayList() didn't return"
- + " the input displaylist for a hardware layer!");
- }
+ updateDisplayListIfDirty(displayList, true);
mHardwareLayer.endRecording(mLocalDirtyRect);
mLocalDirtyRect.setEmpty();
}
@@ -13819,29 +13543,34 @@
* Otherwise, the same display list will be returned (after having been rendered into
* along the way, depending on the invalidation state of the view).
*
- * @param displayList The previous version of this displayList, could be null.
+ * @param renderNode The previous version of this displayList, could be null.
* @param isLayer Whether the requester of the display list is a layer. If so,
* the view will avoid creating a layer inside the resulting display list.
* @return A new or reused DisplayList object.
*/
- private RenderNode getDisplayList(RenderNode displayList, boolean isLayer) {
+ private void updateDisplayListIfDirty(@NonNull RenderNode renderNode, boolean isLayer) {
final HardwareRenderer renderer = getHardwareRenderer();
+ if (renderNode == null) {
+ throw new IllegalArgumentException("RenderNode must not be null");
+ }
if (renderer == null || !canHaveDisplayList()) {
- return null;
+ // can't populate RenderNode, don't try
+ return;
}
- if (((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 ||
- displayList == null || !displayList.isValid() ||
- (!isLayer && mRecreateDisplayList))) {
+ if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
+ || !renderNode.isValid()
+ || (!isLayer && mRecreateDisplayList)) {
// Don't need to recreate the display list, just need to tell our
// children to restore/recreate theirs
- if (displayList != null && displayList.isValid() &&
- !isLayer && !mRecreateDisplayList) {
+ if (renderNode.isValid()
+ && !isLayer
+ && !mRecreateDisplayList) {
mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
dispatchGetDisplayList();
- return displayList;
+ return; // no work needed
}
if (!isLayer) {
@@ -13849,20 +13578,13 @@
// we copy in child display lists into ours in drawChild()
mRecreateDisplayList = true;
}
- if (displayList == null) {
- displayList = RenderNode.create(getClass().getName());
- // If we're creating a new display list, make sure our parent gets invalidated
- // since they will need to recreate their display list to account for this
- // new child display list.
- invalidateParentCaches();
- }
boolean caching = false;
int width = mRight - mLeft;
int height = mBottom - mTop;
int layerType = getLayerType();
- final HardwareCanvas canvas = displayList.start(width, height);
+ final HardwareCanvas canvas = renderNode.start(width, height);
try {
if (!isLayer && layerType != LAYER_TYPE_NONE) {
@@ -13905,12 +13627,12 @@
}
}
} finally {
- displayList.end(renderer, canvas);
- displayList.setCaching(caching);
+ renderNode.end(renderer, canvas);
+ renderNode.setCaching(caching);
if (isLayer) {
- displayList.setLeftTopRightBottom(0, 0, width, height);
+ renderNode.setLeftTopRightBottom(0, 0, width, height);
} else {
- setDisplayListProperties(displayList);
+ setDisplayListProperties(renderNode);
}
if (renderer != getHardwareRenderer()) {
@@ -13925,26 +13647,24 @@
mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
}
-
- return displayList;
}
/**
- * <p>Returns a display list that can be used to draw this view again
- * without executing its draw method.</p>
+ * Returns a RenderNode with View draw content recorded, which can be
+ * used to draw this view again without executing its draw method.
*
- * @return A DisplayList ready to replay, or null if caching is not enabled.
+ * @return A RenderNode ready to replay, or null if caching is not enabled.
*
* @hide
*/
public RenderNode getDisplayList() {
- mDisplayList = getDisplayList(mDisplayList, false);
- return mDisplayList;
+ updateDisplayListIfDirty(mRenderNode, false);
+ return mRenderNode;
}
private void resetDisplayList() {
- if (mDisplayList != null && mDisplayList.isValid()) {
- mDisplayList.destroyDisplayListData();
+ if (mRenderNode.isValid()) {
+ mRenderNode.destroyDisplayListData();
}
if (mBackgroundDisplayList != null && mBackgroundDisplayList.isValid()) {
@@ -14538,21 +14258,16 @@
}
/**
- * This method is called by getDisplayList() when a display list is created or re-rendered.
- * It sets or resets the current value of all properties on that display list (resetting is
- * necessary when a display list is being re-created, because we need to make sure that
- * previously-set transform values
+ * This method is called by getDisplayList() when a display list is recorded for a View.
+ * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
*/
- void setDisplayListProperties(RenderNode displayList) {
- if (displayList != null) {
- displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
- displayList.setHasOverlappingRendering(hasOverlappingRendering());
+ void setDisplayListProperties(RenderNode renderNode) {
+ if (renderNode != null) {
+ renderNode.setHasOverlappingRendering(hasOverlappingRendering());
if (mParent instanceof ViewGroup) {
- displayList.setClipToBounds(
+ renderNode.setClipToBounds(
(((ViewGroup) mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
}
- displayList.setOutline(mOutline);
- displayList.setClipToOutline(getClipToOutline());
float alpha = 1;
if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
@@ -14565,7 +14280,7 @@
alpha = t.getAlpha();
}
if ((transformType & Transformation.TYPE_MATRIX) != 0) {
- displayList.setStaticMatrix(t.getMatrix());
+ renderNode.setStaticMatrix(t.getMatrix());
}
}
}
@@ -14578,23 +14293,9 @@
alpha = 1;
}
}
- displayList.setTransformationInfo(alpha,
- mTransformationInfo.mTranslationX, mTransformationInfo.mTranslationY,
- mTransformationInfo.mTranslationZ,
- mTransformationInfo.mRotation, mTransformationInfo.mRotationX,
- mTransformationInfo.mRotationY, mTransformationInfo.mScaleX,
- mTransformationInfo.mScaleY);
- if (mTransformationInfo.mCamera == null) {
- mTransformationInfo.mCamera = new Camera();
- mTransformationInfo.matrix3D = new Matrix();
- }
- displayList.setCameraDistance(mTransformationInfo.mCamera.getLocationZ());
- if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == PFLAG_PIVOT_EXPLICITLY_SET) {
- displayList.setPivotX(getPivotX());
- displayList.setPivotY(getPivotY());
- }
+ renderNode.setAlpha(alpha);
} else if (alpha < 1) {
- displayList.setAlpha(alpha);
+ renderNode.setAlpha(alpha);
}
}
}
@@ -14641,10 +14342,9 @@
}
transformToApply = parent.getChildTransformation();
} else {
- if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) ==
- PFLAG3_VIEW_IS_ANIMATING_TRANSFORM && mDisplayList != null) {
+ if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
// No longer animating: clear out old animation matrix
- mDisplayList.setAnimationMatrix(null);
+ mRenderNode.setAnimationMatrix(null);
mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
}
if (!useDisplayListProperties &&
@@ -15157,9 +14857,7 @@
if ((mPrivateFlags3 & PFLAG3_OUTLINE_DEFINED) == 0) {
// Outline not currently define, query from background
mOutline = background.getOutline();
- if (mDisplayList != null) {
- mDisplayList.setOutline(mOutline);
- }
+ mRenderNode.setOutline(mOutline);
}
}
@@ -15494,20 +15192,12 @@
mTop = top;
mRight = right;
mBottom = bottom;
- if (mDisplayList != null) {
- mDisplayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
- }
+ mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
mPrivateFlags |= PFLAG_HAS_BOUNDS;
if (sizeChanged) {
- if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
- // A change in dimension means an auto-centered pivot point changes, too
- if (mTransformationInfo != null) {
- mTransformationInfo.mMatrixDirty = true;
- }
- }
sizeChange(newWidth, newHeight, oldWidth, oldHeight);
}
@@ -19081,10 +18771,10 @@
}
}
- class CheckForLongPress implements Runnable {
-
+ private final class CheckForLongPress implements Runnable {
private int mOriginalWindowAttachCount;
+ @Override
public void run() {
if (isPressed() && (mParent != null)
&& mOriginalWindowAttachCount == mWindowAttachCount) {
@@ -19100,14 +18790,20 @@
}
private final class CheckForTap implements Runnable {
+ public float x;
+ public float y;
+
+ @Override
public void run() {
mPrivateFlags &= ~PFLAG_PREPRESSED;
+ setHotspot(R.attr.state_pressed, x, y);
setPressed(true);
checkForLongClick(ViewConfiguration.getTapTimeout());
}
}
private final class PerformClick implements Runnable {
+ @Override
public void run() {
performClick();
}
@@ -19386,7 +19082,9 @@
}
private final class UnsetPressedState implements Runnable {
+ @Override
public void run() {
+ clearHotspot(R.attr.state_pressed);
setPressed(false);
}
}
@@ -19725,7 +19423,7 @@
/**
* The id of the window for accessibility purposes.
*/
- int mAccessibilityWindowId = View.NO_ID;
+ int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
/**
* Flags related to accessibility processing.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index aadaa7f..d2c6302 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -31,7 +31,6 @@
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Build;
-import android.os.Bundle;
import android.os.Parcelable;
import android.os.SystemClock;
import android.util.AttributeSet;
@@ -3174,8 +3173,8 @@
setBooleanFlag(FLAG_CLIP_CHILDREN, clipChildren);
for (int i = 0; i < mChildrenCount; ++i) {
View child = getChildAt(i);
- if (child.mDisplayList != null) {
- child.mDisplayList.setClipToBounds(clipChildren);
+ if (child.mRenderNode != null) {
+ child.mRenderNode.setClipToBounds(clipChildren);
}
}
}
@@ -4450,7 +4449,7 @@
*
* @hide
*/
- public void invalidateChildFast(View child, final Rect dirty) {
+ public void damageChild(View child, final Rect dirty) {
ViewParent parent = this;
final AttachInfo attachInfo = mAttachInfo;
@@ -4473,7 +4472,7 @@
parentVG.invalidate();
parent = null;
} else {
- parent = parentVG.invalidateChildInParentFast(left, top, dirty);
+ parent = parentVG.damageChildInParent(left, top, dirty);
left = parentVG.mLeft;
top = parentVG.mTop;
}
@@ -4495,9 +4494,9 @@
*
* @hide
*/
- protected ViewParent invalidateChildInParentFast(int left, int top, final Rect dirty) {
- if ((mPrivateFlags & PFLAG_DRAWN) == PFLAG_DRAWN ||
- (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) {
+ protected ViewParent damageChildInParent(int left, int top, final Rect dirty) {
+ if ((mPrivateFlags & PFLAG_DRAWN) != 0
+ || (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) != 0) {
dirty.offset(left - mScrollX, top - mScrollY);
if ((mGroupFlags & FLAG_CLIP_CHILDREN) == 0) {
dirty.union(0, 0, mRight - mLeft, mBottom - mTop);
@@ -4610,9 +4609,9 @@
final View v = children[i];
v.mTop += offset;
v.mBottom += offset;
- if (v.mDisplayList != null) {
+ if (v.mRenderNode != null) {
invalidate = true;
- v.mDisplayList.offsetTopAndBottom(offset);
+ v.mRenderNode.offsetTopAndBottom(offset);
}
}
diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java
index 47de780..0cf9ddd 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -290,7 +290,11 @@
}
}
- public void invalidateChildFast(View child, final Rect dirty) {
+ /**
+ * @hide
+ */
+ @Override
+ public void damageChild(View child, final Rect dirty) {
if (mHostView != null) {
// Note: This is not a "fast" invalidation. Would be nice to instead invalidate
// using DisplayList properties and a dirty rect instead of causing a real
@@ -309,9 +313,9 @@
* @hide
*/
@Override
- protected ViewParent invalidateChildInParentFast(int left, int top, Rect dirty) {
+ protected ViewParent damageChildInParent(int left, int top, Rect dirty) {
if (mHostView instanceof ViewGroup) {
- return ((ViewGroup) mHostView).invalidateChildInParentFast(left, top, dirty);
+ return ((ViewGroup) mHostView).damageChildInParent(left, top, dirty);
}
return null;
}
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index 563ffb7..6b21451 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -925,51 +925,41 @@
*/
private void setValue(int propertyConstant, float value) {
final View.TransformationInfo info = mView.mTransformationInfo;
- final RenderNode displayList = mView.mDisplayList;
+ final RenderNode renderNode = mView.mRenderNode;
switch (propertyConstant) {
case TRANSLATION_X:
- info.mTranslationX = value;
- if (displayList != null) displayList.setTranslationX(value);
+ renderNode.setTranslationX(value);
break;
case TRANSLATION_Y:
- info.mTranslationY = value;
- if (displayList != null) displayList.setTranslationY(value);
+ renderNode.setTranslationY(value);
break;
case TRANSLATION_Z:
- info.mTranslationZ = value;
- if (displayList != null) displayList.setTranslationZ(value);
+ renderNode.setTranslationZ(value);
break;
case ROTATION:
- info.mRotation = value;
- if (displayList != null) displayList.setRotation(value);
+ renderNode.setRotation(value);
break;
case ROTATION_X:
- info.mRotationX = value;
- if (displayList != null) displayList.setRotationX(value);
+ renderNode.setRotationX(value);
break;
case ROTATION_Y:
- info.mRotationY = value;
- if (displayList != null) displayList.setRotationY(value);
+ renderNode.setRotationY(value);
break;
case SCALE_X:
- info.mScaleX = value;
- if (displayList != null) displayList.setScaleX(value);
+ renderNode.setScaleX(value);
break;
case SCALE_Y:
- info.mScaleY = value;
- if (displayList != null) displayList.setScaleY(value);
+ renderNode.setScaleY(value);
break;
case X:
- info.mTranslationX = value - mView.mLeft;
- if (displayList != null) displayList.setTranslationX(value - mView.mLeft);
+ renderNode.setTranslationX(value - mView.mLeft);
break;
case Y:
- info.mTranslationY = value - mView.mTop;
- if (displayList != null) displayList.setTranslationY(value - mView.mTop);
+ renderNode.setTranslationY(value - mView.mTop);
break;
case ALPHA:
info.mAlpha = value;
- if (displayList != null) displayList.setAlpha(value);
+ renderNode.setAlpha(value);
break;
}
}
@@ -981,30 +971,30 @@
* @return float The value of the named property
*/
private float getValue(int propertyConstant) {
- final View.TransformationInfo info = mView.mTransformationInfo;
+ final RenderNode node = mView.mRenderNode;
switch (propertyConstant) {
case TRANSLATION_X:
- return info.mTranslationX;
+ return node.getTranslationX();
case TRANSLATION_Y:
- return info.mTranslationY;
+ return node.getTranslationY();
case TRANSLATION_Z:
- return info.mTranslationZ;
+ return node.getTranslationZ();
case ROTATION:
- return info.mRotation;
+ return node.getRotation();
case ROTATION_X:
- return info.mRotationX;
+ return node.getRotationX();
case ROTATION_Y:
- return info.mRotationY;
+ return node.getRotationY();
case SCALE_X:
- return info.mScaleX;
+ return node.getScaleX();
case SCALE_Y:
- return info.mScaleY;
+ return node.getScaleY();
case X:
- return mView.mLeft + info.mTranslationX;
+ return mView.mLeft + node.getTranslationX();
case Y:
- return mView.mTop + info.mTranslationY;
+ return mView.mTop + node.getTranslationY();
case ALPHA:
- return info.mAlpha;
+ return mView.mTransformationInfo.mAlpha;
}
return 0;
}
@@ -1093,7 +1083,7 @@
// Shouldn't happen, but just to play it safe
return;
}
- boolean useDisplayListProperties = mView.mDisplayList != null;
+ boolean useRenderNodeProperties = mView.mRenderNode != null;
// alpha requires slightly different treatment than the other (transform) properties.
// The logic in setAlpha() is not simply setting mAlpha, plus the invalidation
@@ -1101,7 +1091,7 @@
// We track what kinds of properties are set, and how alpha is handled when it is
// set, and perform the invalidation steps appropriately.
boolean alphaHandled = false;
- if (!useDisplayListProperties) {
+ if (!useRenderNodeProperties) {
mView.invalidateParentCaches();
}
float fraction = animation.getAnimatedFraction();
@@ -1123,8 +1113,7 @@
}
}
if ((propertyMask & TRANSFORM_MASK) != 0) {
- mView.mTransformationInfo.mMatrixDirty = true;
- if (!useDisplayListProperties) {
+ if (!useRenderNodeProperties) {
mView.mPrivateFlags |= View.PFLAG_DRAWN; // force another invalidation
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e0e523e..a35c28e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1465,8 +1465,8 @@
mWidth, mHeight);
}
mResizeBuffer.prepare(mWidth, mHeight, false);
- RenderNode layerDisplayList = mResizeBuffer.startRecording();
- HardwareCanvas layerCanvas = layerDisplayList.start(mWidth, mHeight);
+ RenderNode layerRenderNode = mResizeBuffer.startRecording();
+ HardwareCanvas layerCanvas = layerRenderNode.start(mWidth, mHeight);
final int restoreCount = layerCanvas.save();
int yoff;
@@ -1484,9 +1484,9 @@
mTranslator.translateCanvas(layerCanvas);
}
- RenderNode displayList = mView.mDisplayList;
- if (displayList != null && displayList.isValid()) {
- layerCanvas.drawDisplayList(displayList, null,
+ RenderNode renderNode = mView.mRenderNode;
+ if (renderNode != null && renderNode.isValid()) {
+ layerCanvas.drawDisplayList(renderNode, null,
RenderNode.FLAG_CLIP_CHILDREN);
} else {
mView.draw(layerCanvas);
@@ -1499,9 +1499,9 @@
com.android.internal.R.integer.config_mediumAnimTime);
layerCanvas.restoreToCount(restoreCount);
- layerDisplayList.end(mAttachInfo.mHardwareRenderer, layerCanvas);
- layerDisplayList.setCaching(true);
- layerDisplayList.setLeftTopRightBottom(0, 0, mWidth, mHeight);
+ layerRenderNode.end(mAttachInfo.mHardwareRenderer, layerCanvas);
+ layerRenderNode.setCaching(true);
+ layerRenderNode.setLeftTopRightBottom(0, 0, mWidth, mHeight);
mTempRect.set(0, 0, mWidth, mHeight);
mResizeBuffer.endRecording(mTempRect);
mAttachInfo.mHardwareRenderer.flushLayerUpdates();
@@ -2178,9 +2178,9 @@
* @hide
*/
void outputDisplayList(View view) {
- RenderNode displayList = view.getDisplayList();
- if (displayList != null) {
- displayList.output();
+ RenderNode renderNode = view.getDisplayList();
+ if (renderNode != null) {
+ renderNode.output();
}
}
@@ -5218,10 +5218,10 @@
}
private static void getGfxInfo(View view, int[] info) {
- RenderNode displayList = view.mDisplayList;
+ RenderNode renderNode = view.mRenderNode;
info[0]++;
- if (displayList != null) {
- info[1] += 0; /* TODO: Memory used by display lists */
+ if (renderNode != null) {
+ info[1] += 0; /* TODO: Memory used by RenderNodes (properties + DisplayLists) */
}
if (view instanceof ViewGroup) {
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 333e631..14e7951c 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -25,6 +25,7 @@
import android.text.SpannableString;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
import com.android.internal.widget.EditableInputConnection;
import android.R;
@@ -1341,7 +1342,7 @@
if (layout instanceof DynamicLayout) {
if (mTextDisplayLists == null) {
- mTextDisplayLists = new TextDisplayList[ArrayUtils.idealObjectArraySize(0)];
+ mTextDisplayLists = ArrayUtils.emptyArray(TextDisplayList.class);
}
DynamicLayout dynamicLayout = (DynamicLayout) layout;
@@ -1441,10 +1442,7 @@
}
// No available index found, the pool has to grow
- int newSize = ArrayUtils.idealIntArraySize(length + 1);
- TextDisplayList[] displayLists = new TextDisplayList[newSize];
- System.arraycopy(mTextDisplayLists, 0, displayLists, 0, length);
- mTextDisplayLists = displayLists;
+ mTextDisplayLists = GrowingArrayUtils.append(mTextDisplayLists, length, null);
return length;
}
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 64953f8..b47177a 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -24,6 +24,7 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
+import android.os.SystemClock;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.IntProperty;
@@ -1225,6 +1226,15 @@
forwarding = onTouchForwarded(event) || !onForwardingStopped();
} else {
forwarding = onTouchObserved(event) && onForwardingStarted();
+
+ if (forwarding) {
+ // Make sure we cancel any ongoing source event stream.
+ final long now = SystemClock.uptimeMillis();
+ final MotionEvent e = MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL,
+ 0.0f, 0.0f, 0);
+ mSrc.onTouchEvent(e);
+ e.recycle();
+ }
}
mForwarding = forwarding;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 0d3df51..f7d20b53 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1516,6 +1516,75 @@
}
/**
+ * Helper action to set a color filter on a compound drawable on a TextView. Supports relative
+ * (s/t/e/b) or cardinal (l/t/r/b) arrangement.
+ */
+ private class TextViewDrawableColorFilterAction extends Action {
+ public TextViewDrawableColorFilterAction(int viewId, boolean isRelative, int index,
+ int color, PorterDuff.Mode mode) {
+ this.viewId = viewId;
+ this.isRelative = isRelative;
+ this.index = index;
+ this.color = color;
+ this.mode = mode;
+ }
+
+ public TextViewDrawableColorFilterAction(Parcel parcel) {
+ viewId = parcel.readInt();
+ isRelative = (parcel.readInt() != 0);
+ index = parcel.readInt();
+ color = parcel.readInt();
+ mode = readPorterDuffMode(parcel);
+ }
+
+ private PorterDuff.Mode readPorterDuffMode(Parcel parcel) {
+ int mode = parcel.readInt();
+ if (mode >= 0 && mode < PorterDuff.Mode.values().length) {
+ return PorterDuff.Mode.values()[mode];
+ } else {
+ return PorterDuff.Mode.CLEAR;
+ }
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(TAG);
+ dest.writeInt(viewId);
+ dest.writeInt(isRelative ? 1 : 0);
+ dest.writeInt(index);
+ dest.writeInt(color);
+ dest.writeInt(mode.ordinal());
+ }
+
+ @Override
+ public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
+ final TextView target = (TextView) root.findViewById(viewId);
+ if (target == null) return;
+ Drawable[] drawables = isRelative
+ ? target.getCompoundDrawablesRelative()
+ : target.getCompoundDrawables();
+ if (index < 0 || index >= 4) {
+ throw new IllegalStateException("index must be in range [0, 3].");
+ }
+ Drawable d = drawables[index];
+ if (d != null) {
+ d.mutate();
+ d.setColorFilter(color, mode);
+ }
+ }
+
+ public String getActionName() {
+ return "TextViewDrawableColorFilterAction";
+ }
+
+ final boolean isRelative;
+ final int index;
+ final int color;
+ final PorterDuff.Mode mode;
+
+ public final static int TAG = 17;
+ }
+
+ /**
* Simple class used to keep track of memory usage in a RemoteViews.
*
*/
@@ -1686,6 +1755,9 @@
case SetRemoteViewsAdapterList.TAG:
mActions.add(new SetRemoteViewsAdapterList(parcel));
break;
+ case TextViewDrawableColorFilterAction.TAG:
+ mActions.add(new TextViewDrawableColorFilterAction(parcel));
+ break;
default:
throw new ActionException("Tag " + tag + " not found");
}
@@ -1921,6 +1993,28 @@
}
/**
+ * Equivalent to applying a color filter on one of the drawables in
+ * {@link android.widget.TextView#getCompoundDrawablesRelative()}.
+ *
+ * @param viewId The id of the view whose text should change.
+ * @param index The index of the drawable in the array of
+ * {@link android.widget.TextView#getCompoundDrawablesRelative()} to set the color
+ * filter on. Must be in [0, 3].
+ * @param color The color of the color filter. See
+ * {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)}.
+ * @param mode The mode of the color filter. See
+ * {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)}.
+ * @hide
+ */
+ public void setTextViewCompoundDrawablesRelativeColorFilter(int viewId,
+ int index, int color, PorterDuff.Mode mode) {
+ if (index < 0 || index >= 4) {
+ throw new IllegalArgumentException("index must be in range [0, 3].");
+ }
+ addAction(new TextViewDrawableColorFilterAction(viewId, true, index, color, mode));
+ }
+
+ /**
* Equivalent to calling ImageView.setImageResource
*
* @param viewId The id of the view whose drawable should change
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 1eedc5d..d8a6867 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -1171,8 +1171,8 @@
|| !mOnQueryChangeListener.onQueryTextSubmit(query.toString())) {
if (mSearchable != null) {
launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null, query.toString());
- setImeVisibility(false);
}
+ setImeVisibility(false);
dismissSuggestions();
}
}
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 1cda631..595f023 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -35,6 +35,7 @@
import android.view.textservice.TextServicesManager;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
import java.text.BreakIterator;
import java.util.Locale;
@@ -105,9 +106,9 @@
mTextView = textView;
// Arbitrary: these arrays will automatically double their sizes on demand
- final int size = ArrayUtils.idealObjectArraySize(1);
- mIds = new int[size];
- mSpellCheckSpans = new SpellCheckSpan[size];
+ final int size = 1;
+ mIds = ArrayUtils.newUnpaddedIntArray(size);
+ mSpellCheckSpans = new SpellCheckSpan[mIds.length];
setLocale(mTextView.getSpellCheckerLocale());
@@ -184,17 +185,9 @@
if (mIds[i] < 0) return i;
}
- if (mLength == mSpellCheckSpans.length) {
- final int newSize = mLength * 2;
- int[] newIds = new int[newSize];
- SpellCheckSpan[] newSpellCheckSpans = new SpellCheckSpan[newSize];
- System.arraycopy(mIds, 0, newIds, 0, mLength);
- System.arraycopy(mSpellCheckSpans, 0, newSpellCheckSpans, 0, mLength);
- mIds = newIds;
- mSpellCheckSpans = newSpellCheckSpans;
- }
-
- mSpellCheckSpans[mLength] = new SpellCheckSpan();
+ mIds = GrowingArrayUtils.append(mIds, mLength, 0);
+ mSpellCheckSpans = GrowingArrayUtils.append(
+ mSpellCheckSpans, mLength, new SpellCheckSpan());
mLength++;
return mLength - 1;
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 687036c..5e4c143 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5163,12 +5163,12 @@
final int width = mRight - mLeft;
final int padding = getCompoundPaddingLeft() + getCompoundPaddingRight();
final float dx = mLayout.getLineRight(0) - (width - padding);
- canvas.translate(isLayoutRtl ? -dx : +dx, 0.0f);
+ canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
}
if (mMarquee != null && mMarquee.isRunning()) {
final float dx = -mMarquee.getScroll();
- canvas.translate(isLayoutRtl ? -dx : +dx, 0.0f);
+ canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
}
}
@@ -5182,8 +5182,8 @@
}
if (mMarquee != null && mMarquee.shouldDrawGhost()) {
- final int dx = (int) mMarquee.getGhostOffset();
- canvas.translate(isLayoutRtl ? -dx : dx, 0.0f);
+ final float dx = mMarquee.getGhostOffset();
+ canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f);
layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);
}
diff --git a/core/java/android/widget/TimePickerDelegate.java b/core/java/android/widget/TimePickerDelegate.java
index c9a9894..79256e5 100644
--- a/core/java/android/widget/TimePickerDelegate.java
+++ b/core/java/android/widget/TimePickerDelegate.java
@@ -152,11 +152,11 @@
final int headerBackgroundColor = a.getColor(
R.styleable.TimePicker_headerBackgroundColor, 0);
- a.recycle();
-
final int layoutResourceId = a.getResourceId(
R.styleable.TimePicker_internalLayout, R.layout.time_picker_holo);
+ a.recycle();
+
final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index cc51a8b..80e1caa 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -174,7 +174,6 @@
}
private void init(View decor) {
- mContext = decor.getContext();
mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById(
com.android.internal.R.id.action_bar_overlay_layout);
if (mOverlayLayout != null) {
@@ -193,6 +192,7 @@
"with a compatible window decor layout");
}
+ mContext = mActionView.getContext();
mActionView.setContextView(mContextView);
mContextDisplayMode = mActionView.isSplitActionBar() ?
CONTEXT_DISPLAY_SPLIT : CONTEXT_DISPLAY_NORMAL;
diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index b1535e3..882bec9 100644
--- a/core/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -29,8 +29,11 @@
import android.util.SparseArray;
import android.util.TimeUtils;
import android.webkit.WebViewFactory;
-import com.android.internal.util.ArrayUtils;
+
+import com.android.internal.util.GrowingArrayUtils;
+
import dalvik.system.VMRuntime;
+import libcore.util.EmptyArray;
import java.io.IOException;
import java.io.InputStream;
@@ -1621,21 +1624,10 @@
}
int addLongData(int index, int type, int num) {
- int tableLen = mAddLongTable != null ? mAddLongTable.length : 0;
- if (mAddLongTableSize >= tableLen) {
- int newSize = ArrayUtils.idealIntArraySize(tableLen + 1);
- int[] newTable = new int[newSize];
- if (tableLen > 0) {
- System.arraycopy(mAddLongTable, 0, newTable, 0, tableLen);
- }
- mAddLongTable = newTable;
- }
- if (mAddLongTableSize > 0 && mAddLongTableSize - index != 0) {
- System.arraycopy(mAddLongTable, index, mAddLongTable, index + 1,
- mAddLongTableSize - index);
- }
int off = allocLongData(num);
- mAddLongTable[index] = type | off;
+ mAddLongTable = GrowingArrayUtils.insert(
+ mAddLongTable != null ? mAddLongTable : EmptyArray.INT,
+ mAddLongTableSize, index, type | off);
mAddLongTableSize++;
return off;
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 03a053c..ac3274d 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -504,7 +504,7 @@
private String mEnabledInputMethodsStrCache;
private int mCurrentUserId;
- private int[] mRelatedUserIds = new int[0];
+ private int[] mCurrentProfileIds = new int[0];
private static void buildEnabledInputMethodsSettingString(
StringBuilder builder, Pair<String, ArrayList<String>> pair) {
@@ -537,17 +537,17 @@
mCurrentUserId = userId;
}
- public void setRelatedUserIds(int[] relatedUserIds) {
+ public void setCurrentProfileIds(int[] currentProfileIds) {
synchronized (this) {
- mRelatedUserIds = relatedUserIds;
+ mCurrentProfileIds = currentProfileIds;
}
}
- public boolean isRelatedToOrCurrentUser(int userId) {
+ public boolean isCurrentProfile(int userId) {
synchronized (this) {
if (userId == mCurrentUserId) return true;
- for (int i = 0; i < mRelatedUserIds.length; i++) {
- if (userId == mRelatedUserIds[i]) return true;
+ for (int i = 0; i < mCurrentProfileIds.length; i++) {
+ if (userId == mCurrentProfileIds[i]) return true;
}
return false;
}
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index 1766f7b..3301cbe 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -26,8 +26,6 @@
import libcore.io.IoUtils;
-import dalvik.system.Zygote;
-
/**
* Startup class for the wrapper process.
* @hide
@@ -94,7 +92,7 @@
* @param niceName The nice name for the application, or null if none.
* @param targetSdkVersion The target SDK version for the app.
* @param pipeFd The pipe to which the application's pid should be written, or null if none.
- * @param args Arguments for {@link RuntimeInit.main}.
+ * @param args Arguments for {@link RuntimeInit#main}.
*/
public static void execApplication(String invokeWith, String niceName,
int targetSdkVersion, FileDescriptor pipeFd, String[] args) {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
new file mode 100644
index 0000000..c5fa0a1
--- /dev/null
+++ b/core/java/com/android/internal/os/Zygote.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 com.android.internal.os;
+
+
+import dalvik.system.ZygoteHooks;
+import libcore.io.ErrnoException;
+import libcore.io.Libcore;
+
+/** @hide */
+public final class Zygote {
+ /*
+ * Bit values for "debugFlags" argument. The definitions are duplicated
+ * in the native code.
+ */
+
+ /** enable debugging over JDWP */
+ public static final int DEBUG_ENABLE_DEBUGGER = 1;
+ /** enable JNI checks */
+ public static final int DEBUG_ENABLE_CHECKJNI = 1 << 1;
+ /** enable Java programming language "assert" statements */
+ public static final int DEBUG_ENABLE_ASSERT = 1 << 2;
+ /** disable the JIT compiler */
+ public static final int DEBUG_ENABLE_SAFEMODE = 1 << 3;
+ /** Enable logging of third-party JNI activity. */
+ public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4;
+
+ /** No external storage should be mounted. */
+ public static final int MOUNT_EXTERNAL_NONE = 0;
+ /** Single-user external storage should be mounted. */
+ public static final int MOUNT_EXTERNAL_SINGLEUSER = 1;
+ /** Multi-user external storage should be mounted. */
+ public static final int MOUNT_EXTERNAL_MULTIUSER = 2;
+ /** All multi-user external storage should be mounted. */
+ public static final int MOUNT_EXTERNAL_MULTIUSER_ALL = 3;
+
+ private static final ZygoteHooks VM_HOOKS = new ZygoteHooks();
+
+ private Zygote() {}
+
+ /**
+ * Forks a new VM instance. The current VM must have been started
+ * with the -Xzygote flag. <b>NOTE: new instance keeps all
+ * root capabilities. The new process is expected to call capset()</b>.
+ *
+ * @param uid the UNIX uid that the new process should setuid() to after
+ * fork()ing and and before spawning any threads.
+ * @param gid the UNIX gid that the new process should setgid() to after
+ * fork()ing and and before spawning any threads.
+ * @param gids null-ok; a list of UNIX gids that the new process should
+ * setgroups() to after fork and before spawning any threads.
+ * @param debugFlags bit flags that enable debugging features.
+ * @param rlimits null-ok an array of rlimit tuples, with the second
+ * dimension having a length of 3 and representing
+ * (resource, rlim_cur, rlim_max). These are set via the posix
+ * setrlimit(2) call.
+ * @param seInfo null-ok a string specifying SELinux information for
+ * the new process.
+ * @param niceName null-ok a string specifying the process name.
+ * @param fdsToClose an array of ints, holding one or more POSIX
+ * file descriptor numbers that are to be closed by the child
+ * (and replaced by /dev/null) after forking. An integer value
+ * of -1 in any entry in the array means "ignore this one".
+ *
+ * @return 0 if this is the child, pid of the child
+ * if this is the parent, or -1 on error.
+ */
+ public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
+ int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose) {
+ VM_HOOKS.preFork();
+ int pid = nativeForkAndSpecialize(
+ uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose);
+ VM_HOOKS.postForkCommon();
+ return pid;
+ }
+
+ native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,
+ int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose);
+
+ /**
+ * Special method to start the system server process. In addition to the
+ * common actions performed in forkAndSpecialize, the pid of the child
+ * process is recorded such that the death of the child process will cause
+ * zygote to exit.
+ *
+ * @param uid the UNIX uid that the new process should setuid() to after
+ * fork()ing and and before spawning any threads.
+ * @param gid the UNIX gid that the new process should setgid() to after
+ * fork()ing and and before spawning any threads.
+ * @param gids null-ok; a list of UNIX gids that the new process should
+ * setgroups() to after fork and before spawning any threads.
+ * @param debugFlags bit flags that enable debugging features.
+ * @param rlimits null-ok an array of rlimit tuples, with the second
+ * dimension having a length of 3 and representing
+ * (resource, rlim_cur, rlim_max). These are set via the posix
+ * setrlimit(2) call.
+ * @param permittedCapabilities argument for setcap()
+ * @param effectiveCapabilities argument for setcap()
+ *
+ * @return 0 if this is the child, pid of the child
+ * if this is the parent, or -1 on error.
+ */
+ public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
+ int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
+ VM_HOOKS.preFork();
+ int pid = nativeForkSystemServer(
+ uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
+ VM_HOOKS.postForkCommon();
+ return pid;
+ }
+
+ native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
+ int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
+
+ private static void callPostForkChildHooks(int debugFlags) {
+ VM_HOOKS.postForkChild(debugFlags);
+ }
+
+
+ /**
+ * Executes "/system/bin/sh -c <command>" using the exec() system call.
+ * This method throws a runtime exception if exec() failed, otherwise, this
+ * method never returns.
+ *
+ * @param command The shell command to execute.
+ */
+ public static void execShell(String command) {
+ String[] args = { "/system/bin/sh", "-c", command };
+ try {
+ Libcore.os.execv(args[0], args);
+ } catch (ErrnoException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Appends quotes shell arguments to the specified string builder.
+ * The arguments are quoted using single-quotes, escaped if necessary,
+ * prefixed with a space, and appended to the command.
+ *
+ * @param command A string builder for the shell command being constructed.
+ * @param args An array of argument strings to be quoted and appended to the command.
+ * @see #execShell(String)
+ */
+ public static void appendQuotedShellArgs(StringBuilder command, String[] args) {
+ for (String arg : args) {
+ command.append(" '").append(arg.replace("'", "'\\''")).append("'");
+ }
+ }
+}
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index f9a1f89..aad534c 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -24,7 +24,6 @@
import android.util.Log;
import dalvik.system.PathClassLoader;
-import dalvik.system.Zygote;
import java.io.BufferedReader;
import java.io.DataInputStream;
@@ -807,7 +806,7 @@
/**
* Applies invoke-with system properties to the zygote arguments.
*
- * @param parsedArgs non-null; zygote args
+ * @param args non-null; zygote args
*/
public static void applyInvokeWithSystemProperty(Arguments args) {
if (args.invokeWith == null && args.niceName != null) {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 05c57e8..66cc120 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -32,7 +32,6 @@
import android.util.Log;
import dalvik.system.VMRuntime;
-import dalvik.system.Zygote;
import libcore.io.IoUtils;
import libcore.io.Libcore;
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 9137d3c..d177410 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -16,11 +16,10 @@
package com.android.internal.util;
-import java.lang.reflect.Array;
+import dalvik.system.VMRuntime;
+import libcore.util.EmptyArray;
-// XXX these should be changed to reflect the actual memory allocator we use.
-// it looks like right now objects want to be powers of 2 minus 8
-// and the array size eats another 4 bytes
+import java.lang.reflect.Array;
/**
* ArrayUtils contains some methods that you can call to find out
@@ -28,46 +27,42 @@
*/
public class ArrayUtils
{
- private static Object[] EMPTY = new Object[0];
private static final int CACHE_SIZE = 73;
private static Object[] sCache = new Object[CACHE_SIZE];
private ArrayUtils() { /* cannot be instantiated */ }
- public static int idealByteArraySize(int need) {
- for (int i = 4; i < 32; i++)
- if (need <= (1 << i) - 12)
- return (1 << i) - 12;
-
- return need;
+ public static byte[] newUnpaddedByteArray(int minLen) {
+ return (byte[])VMRuntime.getRuntime().newUnpaddedArray(byte.class, minLen);
}
- public static int idealBooleanArraySize(int need) {
- return idealByteArraySize(need);
+ public static char[] newUnpaddedCharArray(int minLen) {
+ return (char[])VMRuntime.getRuntime().newUnpaddedArray(char.class, minLen);
}
- public static int idealShortArraySize(int need) {
- return idealByteArraySize(need * 2) / 2;
+ public static int[] newUnpaddedIntArray(int minLen) {
+ return (int[])VMRuntime.getRuntime().newUnpaddedArray(int.class, minLen);
}
- public static int idealCharArraySize(int need) {
- return idealByteArraySize(need * 2) / 2;
+ public static boolean[] newUnpaddedBooleanArray(int minLen) {
+ return (boolean[])VMRuntime.getRuntime().newUnpaddedArray(boolean.class, minLen);
}
- public static int idealIntArraySize(int need) {
- return idealByteArraySize(need * 4) / 4;
+ public static long[] newUnpaddedLongArray(int minLen) {
+ return (long[])VMRuntime.getRuntime().newUnpaddedArray(long.class, minLen);
}
- public static int idealFloatArraySize(int need) {
- return idealByteArraySize(need * 4) / 4;
+ public static float[] newUnpaddedFloatArray(int minLen) {
+ return (float[])VMRuntime.getRuntime().newUnpaddedArray(float.class, minLen);
}
- public static int idealObjectArraySize(int need) {
- return idealByteArraySize(need * 4) / 4;
+ public static Object[] newUnpaddedObjectArray(int minLen) {
+ return (Object[])VMRuntime.getRuntime().newUnpaddedArray(Object.class, minLen);
}
- public static int idealLongArraySize(int need) {
- return idealByteArraySize(need * 8) / 8;
+ @SuppressWarnings("unchecked")
+ public static <T> T[] newUnpaddedArray(Class<T> clazz, int minLen) {
+ return (T[])VMRuntime.getRuntime().newUnpaddedArray(clazz, minLen);
}
/**
@@ -102,9 +97,10 @@
* it will return the same empty array every time to avoid reallocation,
* although this is not guaranteed.
*/
+ @SuppressWarnings("unchecked")
public static <T> T[] emptyArray(Class<T> kind) {
if (kind == Object.class) {
- return (T[]) EMPTY;
+ return (T[]) EmptyArray.OBJECT;
}
int bucket = ((System.identityHashCode(kind) / 8) & 0x7FFFFFFF) % CACHE_SIZE;
diff --git a/core/java/com/android/internal/util/GrowingArrayUtils.java b/core/java/com/android/internal/util/GrowingArrayUtils.java
new file mode 100644
index 0000000..b4d2d730
--- /dev/null
+++ b/core/java/com/android/internal/util/GrowingArrayUtils.java
@@ -0,0 +1,196 @@
+/*
+ * 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.internal.util;
+
+/**
+ * A helper class that aims to provide comparable growth performance to ArrayList, but on primitive
+ * arrays. Common array operations are implemented for efficient use in dynamic containers.
+ *
+ * All methods in this class assume that the length of an array is equivalent to its capacity and
+ * NOT the number of elements in the array. The current size of the array is always passed in as a
+ * parameter.
+ *
+ * @hide
+ */
+public final class GrowingArrayUtils {
+
+ /**
+ * Appends an element to the end of the array, growing the array if there is no more room.
+ * @param array The array to which to append the element. This must NOT be null.
+ * @param currentSize The number of elements in the array. Must be less than or equal to
+ * array.length.
+ * @param element The element to append.
+ * @return the array to which the element was appended. This may be different than the given
+ * array.
+ */
+ public static <T> T[] append(T[] array, int currentSize, T element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 > array.length) {
+ @SuppressWarnings("unchecked")
+ T[] newArray = ArrayUtils.newUnpaddedArray(
+ (Class<T>) array.getClass().getComponentType(), growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, currentSize);
+ array = newArray;
+ }
+ array[currentSize] = element;
+ return array;
+ }
+
+ /**
+ * Primitive int version of {@link #append(Object[], int, Object)}.
+ */
+ public static int[] append(int[] array, int currentSize, int element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 > array.length) {
+ int[] newArray = ArrayUtils.newUnpaddedIntArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, currentSize);
+ array = newArray;
+ }
+ array[currentSize] = element;
+ return array;
+ }
+
+ /**
+ * Primitive long version of {@link #append(Object[], int, Object)}.
+ */
+ public static long[] append(long[] array, int currentSize, long element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 > array.length) {
+ long[] newArray = ArrayUtils.newUnpaddedLongArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, currentSize);
+ array = newArray;
+ }
+ array[currentSize] = element;
+ return array;
+ }
+
+ /**
+ * Primitive boolean version of {@link #append(Object[], int, Object)}.
+ */
+ public static boolean[] append(boolean[] array, int currentSize, boolean element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 > array.length) {
+ boolean[] newArray = ArrayUtils.newUnpaddedBooleanArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, currentSize);
+ array = newArray;
+ }
+ array[currentSize] = element;
+ return array;
+ }
+
+ /**
+ * Inserts an element into the array at the specified index, growing the array if there is no
+ * more room.
+ *
+ * @param array The array to which to append the element. Must NOT be null.
+ * @param currentSize The number of elements in the array. Must be less than or equal to
+ * array.length.
+ * @param element The element to insert.
+ * @return the array to which the element was appended. This may be different than the given
+ * array.
+ */
+ public static <T> T[] insert(T[] array, int currentSize, int index, T element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 <= array.length) {
+ System.arraycopy(array, index, array, index + 1, currentSize - index);
+ array[index] = element;
+ return array;
+ }
+
+ @SuppressWarnings("unchecked")
+ T[] newArray = ArrayUtils.newUnpaddedArray((Class<T>)array.getClass().getComponentType(),
+ growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, index);
+ newArray[index] = element;
+ System.arraycopy(array, index, newArray, index + 1, array.length - index);
+ return newArray;
+ }
+
+ /**
+ * Primitive int version of {@link #insert(Object[], int, int, Object)}.
+ */
+ public static int[] insert(int[] array, int currentSize, int index, int element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 <= array.length) {
+ System.arraycopy(array, index, array, index + 1, currentSize - index);
+ array[index] = element;
+ return array;
+ }
+
+ int[] newArray = ArrayUtils.newUnpaddedIntArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, index);
+ newArray[index] = element;
+ System.arraycopy(array, index, newArray, index + 1, array.length - index);
+ return newArray;
+ }
+
+ /**
+ * Primitive long version of {@link #insert(Object[], int, int, Object)}.
+ */
+ public static long[] insert(long[] array, int currentSize, int index, long element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 <= array.length) {
+ System.arraycopy(array, index, array, index + 1, currentSize - index);
+ array[index] = element;
+ return array;
+ }
+
+ long[] newArray = ArrayUtils.newUnpaddedLongArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, index);
+ newArray[index] = element;
+ System.arraycopy(array, index, newArray, index + 1, array.length - index);
+ return newArray;
+ }
+
+ /**
+ * Primitive boolean version of {@link #insert(Object[], int, int, Object)}.
+ */
+ public static boolean[] insert(boolean[] array, int currentSize, int index, boolean element) {
+ assert currentSize <= array.length;
+
+ if (currentSize + 1 <= array.length) {
+ System.arraycopy(array, index, array, index + 1, currentSize - index);
+ array[index] = element;
+ return array;
+ }
+
+ boolean[] newArray = ArrayUtils.newUnpaddedBooleanArray(growSize(currentSize));
+ System.arraycopy(array, 0, newArray, 0, index);
+ newArray[index] = element;
+ System.arraycopy(array, index, newArray, index + 1, array.length - index);
+ return newArray;
+ }
+
+ /**
+ * Given the current size of an array, returns an ideal size to which the array should grow.
+ * This is typically double the given size, but should not be relied upon to do so in the
+ * future.
+ */
+ public static int growSize(int currentSize) {
+ return currentSize <= 4 ? 8 : currentSize * 2;
+ }
+
+ // Uninstantiable
+ private GrowingArrayUtils() {}
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ImageUtils.java b/core/java/com/android/internal/util/ImageUtils.java
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/ImageUtils.java
rename to core/java/com/android/internal/util/ImageUtils.java
index 540ba20..a5ce6e0ca 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageUtils.java
+++ b/core/java/com/android/internal/util/ImageUtils.java
@@ -14,12 +14,14 @@
* limitations under the License
*/
-package com.android.systemui;
+package com.android.internal.util;
import android.graphics.Bitmap;
/**
* Utility class for image analysis and processing.
+ *
+ * @hide
*/
public class ImageUtils {
@@ -65,7 +67,7 @@
*
* Note that really transparent colors are always grayscale.
*/
- public boolean isGrayscale(int color) {
+ public static boolean isGrayscale(int color) {
int alpha = 0xFF & (color >> 24);
if (alpha < ALPHA_TOLERANCE) {
return true;
diff --git a/core/java/com/android/internal/util/LegacyNotificationUtil.java b/core/java/com/android/internal/util/LegacyNotificationUtil.java
new file mode 100644
index 0000000..0394bbc
--- /dev/null
+++ b/core/java/com/android/internal/util/LegacyNotificationUtil.java
@@ -0,0 +1,193 @@
+/*
+ * 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.internal.util;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.style.TextAppearanceSpan;
+import android.util.Log;
+import android.util.Pair;
+
+import java.util.Arrays;
+import java.util.WeakHashMap;
+
+/**
+ * Helper class to process legacy (Holo) notifications to make them look like quantum notifications.
+ *
+ * @hide
+ */
+public class LegacyNotificationUtil {
+
+ private static final String TAG = "LegacyNotificationUtil";
+
+ private static final Object sLock = new Object();
+ private static LegacyNotificationUtil 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() {
+ synchronized (sLock) {
+ if (sInstance == null) {
+ sInstance = new LegacyNotificationUtil();
+ }
+ return sInstance;
+ }
+ }
+
+ /**
+ * Checks whether a bitmap is grayscale. Grayscale here means "very close to a perfect
+ * gray".
+ *
+ * @param bitmap The bitmap to test.
+ * @return Whether the bitmap is grayscale.
+ */
+ public boolean isGrayscale(Bitmap bitmap) {
+ synchronized (sLock) {
+ Pair<Boolean, Integer> cached = mGrayscaleBitmapCache.get(bitmap);
+ if (cached != null) {
+ if (cached.second == bitmap.getGenerationId()) {
+ return cached.first;
+ }
+ }
+ }
+ boolean result;
+ int generationId;
+ synchronized (mImageUtils) {
+ result = mImageUtils.isGrayscale(bitmap);
+
+ // generationId and the check whether the Bitmap is grayscale can't be read atomically
+ // here. However, since the thread is in the process of posting the notification, we can
+ // assume that it doesn't modify the bitmap while we are checking the pixels.
+ generationId = bitmap.getGenerationId();
+ }
+ synchronized (sLock) {
+ mGrayscaleBitmapCache.put(bitmap, Pair.create(result, generationId));
+ }
+ return result;
+ }
+
+ /**
+ * Checks whether a drawable is grayscale. Grayscale here means "very close to a perfect
+ * gray".
+ *
+ * @param d The drawable to test.
+ * @return Whether the drawable is grayscale.
+ */
+ public boolean isGrayscale(Drawable d) {
+ if (d == null) {
+ return false;
+ } else if (d instanceof BitmapDrawable) {
+ BitmapDrawable bd = (BitmapDrawable) d;
+ return bd.getBitmap() != null && isGrayscale(bd.getBitmap());
+ } else if (d instanceof AnimationDrawable) {
+ AnimationDrawable ad = (AnimationDrawable) d;
+ int count = ad.getNumberOfFrames();
+ return count > 0 && isGrayscale(ad.getFrame(0));
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Checks whether a drawable with a resoure id is grayscale. Grayscale here means "very close
+ * to a perfect gray".
+ *
+ * @param context The context to load the drawable from.
+ * @return Whether the drawable is grayscale.
+ */
+ public boolean isGrayscale(Context context, int drawableResId) {
+ if (drawableResId != 0) {
+ try {
+ return isGrayscale(context.getDrawable(drawableResId));
+ } catch (Resources.NotFoundException ex) {
+ Log.e(TAG, "Drawable not found: " + drawableResId);
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Inverts all the grayscale colors set by {@link android.text.style.TextAppearanceSpan}s on
+ * the text.
+ *
+ * @param charSequence The text to process.
+ * @return The color inverted text.
+ */
+ public CharSequence invertCharSequenceColors(CharSequence charSequence) {
+ if (charSequence instanceof Spanned) {
+ Spanned ss = (Spanned) charSequence;
+ Object[] spans = ss.getSpans(0, ss.length(), Object.class);
+ SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
+ for (Object span : spans) {
+ Object resultSpan = span;
+ if (span instanceof TextAppearanceSpan) {
+ resultSpan = processTextAppearanceSpan((TextAppearanceSpan) span);
+ }
+ builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span),
+ ss.getSpanFlags(span));
+ }
+ return builder;
+ }
+ return charSequence;
+ }
+
+ private TextAppearanceSpan processTextAppearanceSpan(TextAppearanceSpan span) {
+ ColorStateList colorStateList = span.getTextColor();
+ if (colorStateList != null) {
+ int[] colors = colorStateList.getColors();
+ boolean changed = false;
+ for (int i = 0; i < colors.length; i++) {
+ if (ImageUtils.isGrayscale(colors[i])) {
+
+ // Allocate a new array so we don't change the colors in the old color state
+ // list.
+ if (!changed) {
+ colors = Arrays.copyOf(colors, colors.length);
+ }
+ colors[i] = processColor(colors[i]);
+ changed = true;
+ }
+ }
+ if (changed) {
+ return new TextAppearanceSpan(
+ span.getFamily(), span.getTextStyle(), span.getTextSize(),
+ new ColorStateList(colorStateList.getStates(), colors),
+ span.getLinkTextColor());
+ }
+ }
+ return span;
+ }
+
+ private int processColor(int color) {
+ return Color.argb(Color.alpha(color),
+ 255 - Color.red(color),
+ 255 - Color.green(color),
+ 255 - Color.blue(color));
+ }
+}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index e5aaf7e..b9bc54d 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -19,11 +19,14 @@
import android.Manifest;
import android.app.ActivityManagerNative;
import android.app.admin.DevicePolicyManager;
+import android.app.trust.TrustManager;
import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.net.Uri;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -46,6 +49,8 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
/**
@@ -145,6 +150,8 @@
private static final String LOCK_SCREEN_OWNER_INFO_ENABLED =
Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
+ private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
+
private final Context mContext;
private final ContentResolver mContentResolver;
private DevicePolicyManager mDevicePolicyManager;
@@ -167,6 +174,15 @@
return mDevicePolicyManager;
}
+ private TrustManager getTrustManager() {
+ TrustManager trust = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
+ if (trust == null) {
+ Log.e(TAG, "Can't get TrustManagerService: is it running?",
+ new IllegalStateException("Stack trace:"));
+ }
+ return trust;
+ }
+
/**
* @param contentResolver Used to look up and save settings.
*/
@@ -242,10 +258,14 @@
*/
public void reportFailedPasswordAttempt() {
getDevicePolicyManager().reportFailedPasswordAttempt(getCurrentOrCallingUserId());
+ getTrustManager().reportUnlockAttempt(false /* authenticated */,
+ getCurrentOrCallingUserId());
}
public void reportSuccessfulPasswordAttempt() {
getDevicePolicyManager().reportSuccessfulPasswordAttempt(getCurrentOrCallingUserId());
+ getTrustManager().reportUnlockAttempt(true /* authenticated */,
+ getCurrentOrCallingUserId());
}
public void setCurrentUser(int userId) {
@@ -510,11 +530,12 @@
*/
public void saveLockPattern(List<LockPatternView.Cell> pattern, boolean isFallback) {
try {
- getLockSettings().setLockPattern(patternToString(pattern), getCurrentOrCallingUserId());
+ int userId = getCurrentOrCallingUserId();
+ getLockSettings().setLockPattern(patternToString(pattern), userId);
DevicePolicyManager dpm = getDevicePolicyManager();
if (pattern != null) {
- int userHandle = getCurrentOrCallingUserId();
+ int userHandle = userId;
if (userHandle == UserHandle.USER_OWNER) {
String stringPattern = patternToString(pattern);
updateEncryptionPassword(StorageManager.CRYPT_TYPE_PATTERN, stringPattern);
@@ -525,18 +546,18 @@
deleteGallery();
setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
- pattern.size(), 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId());
+ pattern.size(), 0, 0, 0, 0, 0, 0, userId);
} else {
setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK);
setLong(PASSWORD_TYPE_ALTERNATE_KEY,
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
finishBiometricWeak();
dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK,
- 0, 0, 0, 0, 0, 0, 0, getCurrentOrCallingUserId());
+ 0, 0, 0, 0, 0, 0, 0, userId);
}
} else {
dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0,
- 0, 0, 0, 0, 0, getCurrentOrCallingUserId());
+ 0, 0, 0, 0, 0, userId);
}
} catch (RemoteException re) {
Log.e(TAG, "Couldn't save lock pattern " + re);
@@ -1388,4 +1409,38 @@
setBoolean(LOCKSCREEN_WIDGETS_ENABLED, enabled, userId);
}
+ public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents) {
+ setEnabledTrustAgents(activeTrustAgents, getCurrentOrCallingUserId());
+ }
+
+ public List<ComponentName> getEnabledTrustAgents() {
+ return getEnabledTrustAgents(getCurrentOrCallingUserId());
+ }
+
+ public void setEnabledTrustAgents(Collection<ComponentName> activeTrustAgents, int userId) {
+ StringBuilder sb = new StringBuilder();
+ for (ComponentName cn : activeTrustAgents) {
+ if (sb.length() > 0) {
+ sb.append(',');
+ }
+ sb.append(cn.flattenToShortString());
+ }
+ setString(ENABLED_TRUST_AGENTS, sb.toString(), userId);
+ getTrustManager().reportEnabledTrustAgentsChanged(getCurrentOrCallingUserId());
+ }
+
+ public List<ComponentName> getEnabledTrustAgents(int userId) {
+ String serialized = getString(ENABLED_TRUST_AGENTS, userId);
+ if (TextUtils.isEmpty(serialized)) {
+ return null;
+ }
+ String[] split = serialized.split(",");
+ ArrayList<ComponentName> activeTrustAgents = new ArrayList<ComponentName>(split.length);
+ for (String s : split) {
+ if (!TextUtils.isEmpty(s)) {
+ activeTrustAgents.add(ComponentName.unflattenFromString(s));
+ }
+ }
+ return activeTrustAgents;
+ }
}
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 26cb4e5..36ed344 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -32,6 +32,7 @@
import android.os.Parcelable;
import android.os.SystemClock;
import android.util.AttributeSet;
+import android.util.TypedValue;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
@@ -260,13 +261,23 @@
mPathPaint.setAntiAlias(true);
mPathPaint.setDither(true);
- mPathPaint.setColor(Color.WHITE); // TODO this should be from the style
+
+ int defaultColor = Color.WHITE;
+ TypedValue outValue = new TypedValue();
+ if (context.getTheme().resolveAttribute(android.R.attr.textColorPrimary, outValue, true)) {
+ defaultColor = context.getResources().getColor(outValue.resourceId);
+ }
+
+ final int color = a.getColor(R.styleable.LockPatternView_pathColor, defaultColor);
+ mPathPaint.setColor(color);
+
mPathPaint.setAlpha(mStrokeAlpha);
mPathPaint.setStyle(Paint.Style.STROKE);
mPathPaint.setStrokeJoin(Paint.Join.ROUND);
mPathPaint.setStrokeCap(Paint.Cap.ROUND);
// lot's of bitmaps!
+ // TODO: those bitmaps are hardcoded to the Holo Theme which should not be the case!
mBitmapBtnDefault = getBitmapFor(R.drawable.btn_code_lock_default_holo);
mBitmapBtnTouched = getBitmapFor(R.drawable.btn_code_lock_touched_holo);
mBitmapCircleDefault = getBitmapFor(R.drawable.indicator_code_lock_point_area_default_holo);
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
deleted file mode 100644
index 4648f39..0000000
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ /dev/null
@@ -1,1270 +0,0 @@
-/*
- * Copyright (C) 2011 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.widget.multiwaveview;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.media.AudioManager;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.Vibrator;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
-
-import com.android.internal.R;
-
-import java.util.ArrayList;
-
-/**
- * A special widget containing a center and outer ring. Moving the center ring to the outer ring
- * causes an event that can be caught by implementing OnTriggerListener.
- */
-public class MultiWaveView extends View {
- private static final String TAG = "MultiWaveView";
- private static final boolean DEBUG = false;
-
- // Wave state machine
- private static final int STATE_IDLE = 0;
- private static final int STATE_START = 1;
- private static final int STATE_FIRST_TOUCH = 2;
- private static final int STATE_TRACKING = 3;
- private static final int STATE_SNAP = 4;
- private static final int STATE_FINISH = 5;
-
- // Animation properties.
- private static final float SNAP_MARGIN_DEFAULT = 20.0f; // distance to ring before we snap to it
-
- public interface OnTriggerListener {
- int NO_HANDLE = 0;
- int CENTER_HANDLE = 1;
- public void onGrabbed(View v, int handle);
- public void onReleased(View v, int handle);
- public void onTrigger(View v, int target);
- public void onGrabbedStateChange(View v, int handle);
- public void onFinishFinalAnimation();
- }
-
- // Tuneable parameters for animation
- private static final int CHEVRON_INCREMENTAL_DELAY = 160;
- private static final int CHEVRON_ANIMATION_DURATION = 850;
- private static final int RETURN_TO_HOME_DELAY = 1200;
- private static final int RETURN_TO_HOME_DURATION = 200;
- private static final int HIDE_ANIMATION_DELAY = 200;
- private static final int HIDE_ANIMATION_DURATION = 200;
- private static final int SHOW_ANIMATION_DURATION = 200;
- private static final int SHOW_ANIMATION_DELAY = 50;
- private static final int INITIAL_SHOW_HANDLE_DURATION = 200;
-
- private static final float TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED = 1.3f;
- private static final float TARGET_SCALE_EXPANDED = 1.0f;
- private static final float TARGET_SCALE_COLLAPSED = 0.8f;
- private static final float RING_SCALE_EXPANDED = 1.0f;
- private static final float RING_SCALE_COLLAPSED = 0.5f;
-
- private TimeInterpolator mChevronAnimationInterpolator = Ease.Quad.easeOut;
-
- private ArrayList<TargetDrawable> mTargetDrawables = new ArrayList<TargetDrawable>();
- private ArrayList<TargetDrawable> mChevronDrawables = new ArrayList<TargetDrawable>();
- private AnimationBundle mChevronAnimations = new AnimationBundle();
- private AnimationBundle mTargetAnimations = new AnimationBundle();
- private AnimationBundle mHandleAnimations = new AnimationBundle();
- private ArrayList<String> mTargetDescriptions;
- private ArrayList<String> mDirectionDescriptions;
- private OnTriggerListener mOnTriggerListener;
- private TargetDrawable mHandleDrawable;
- private TargetDrawable mOuterRing;
- private Vibrator mVibrator;
-
- private int mFeedbackCount = 3;
- private int mVibrationDuration = 0;
- private int mGrabbedState;
- private int mActiveTarget = -1;
- private float mTapRadius;
- private float mWaveCenterX;
- private float mWaveCenterY;
- private int mMaxTargetHeight;
- private int mMaxTargetWidth;
-
- private float mOuterRadius = 0.0f;
- private float mSnapMargin = 0.0f;
- private boolean mDragging;
- private int mNewTargetResources;
-
- private class AnimationBundle extends ArrayList<Tweener> {
- private static final long serialVersionUID = 0xA84D78726F127468L;
- private boolean mSuspended;
-
- public void start() {
- if (mSuspended) return; // ignore attempts to start animations
- final int count = size();
- for (int i = 0; i < count; i++) {
- Tweener anim = get(i);
- anim.animator.start();
- }
- }
-
- public void cancel() {
- final int count = size();
- for (int i = 0; i < count; i++) {
- Tweener anim = get(i);
- anim.animator.cancel();
- }
- clear();
- }
-
- public void stop() {
- final int count = size();
- for (int i = 0; i < count; i++) {
- Tweener anim = get(i);
- anim.animator.end();
- }
- clear();
- }
-
- public void setSuspended(boolean suspend) {
- mSuspended = suspend;
- }
- };
-
- private AnimatorListener mResetListener = new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animator) {
- switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
- dispatchOnFinishFinalAnimation();
- }
- };
-
- private AnimatorListener mResetListenerWithPing = new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animator) {
- ping();
- switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
- dispatchOnFinishFinalAnimation();
- }
- };
-
- private AnimatorUpdateListener mUpdateListener = new AnimatorUpdateListener() {
- public void onAnimationUpdate(ValueAnimator animation) {
- invalidateGlobalRegion(mHandleDrawable);
- invalidate();
- }
- };
-
- private boolean mAnimatingTargets;
- private AnimatorListener mTargetUpdateListener = new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animator) {
- if (mNewTargetResources != 0) {
- internalSetTargetResources(mNewTargetResources);
- mNewTargetResources = 0;
- hideTargets(false, false);
- }
- mAnimatingTargets = false;
- }
- };
- private int mTargetResourceId;
- private int mTargetDescriptionsResourceId;
- private int mDirectionDescriptionsResourceId;
- private boolean mAlwaysTrackFinger;
- private int mHorizontalInset;
- private int mVerticalInset;
- private int mGravity = Gravity.TOP;
- private boolean mInitialLayout = true;
- private Tweener mBackgroundAnimator;
-
- public MultiWaveView(Context context) {
- this(context, null);
- }
-
- public MultiWaveView(Context context, AttributeSet attrs) {
- super(context, attrs);
- Resources res = context.getResources();
-
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MultiWaveView);
- mOuterRadius = a.getDimension(R.styleable.MultiWaveView_outerRadius, mOuterRadius);
- mSnapMargin = a.getDimension(R.styleable.MultiWaveView_snapMargin, mSnapMargin);
- mVibrationDuration = a.getInt(R.styleable.MultiWaveView_vibrationDuration,
- mVibrationDuration);
- mFeedbackCount = a.getInt(R.styleable.MultiWaveView_feedbackCount,
- mFeedbackCount);
- mHandleDrawable = new TargetDrawable(res,
- a.peekValue(R.styleable.MultiWaveView_handleDrawable).resourceId);
- mTapRadius = mHandleDrawable.getWidth()/2;
- mOuterRing = new TargetDrawable(res,
- a.peekValue(R.styleable.MultiWaveView_waveDrawable).resourceId);
- mAlwaysTrackFinger = a.getBoolean(R.styleable.MultiWaveView_alwaysTrackFinger, false);
-
- // Read array of chevron drawables
- TypedValue outValue = new TypedValue();
- if (a.getValue(R.styleable.MultiWaveView_chevronDrawables, outValue)) {
- ArrayList<TargetDrawable> chevrons = loadDrawableArray(outValue.resourceId);
- for (int i = 0; i < chevrons.size(); i++) {
- final TargetDrawable chevron = chevrons.get(i);
- for (int k = 0; k < mFeedbackCount; k++) {
- mChevronDrawables.add(chevron == null ? null : new TargetDrawable(chevron));
- }
- }
- }
-
- // Read array of target drawables
- if (a.getValue(R.styleable.MultiWaveView_targetDrawables, outValue)) {
- internalSetTargetResources(outValue.resourceId);
- }
- if (mTargetDrawables == null || mTargetDrawables.size() == 0) {
- throw new IllegalStateException("Must specify at least one target drawable");
- }
-
- // Read array of target descriptions
- if (a.getValue(R.styleable.MultiWaveView_targetDescriptions, outValue)) {
- final int resourceId = outValue.resourceId;
- if (resourceId == 0) {
- throw new IllegalStateException("Must specify target descriptions");
- }
- setTargetDescriptionsResourceId(resourceId);
- }
-
- // Read array of direction descriptions
- if (a.getValue(R.styleable.MultiWaveView_directionDescriptions, outValue)) {
- final int resourceId = outValue.resourceId;
- if (resourceId == 0) {
- throw new IllegalStateException("Must specify direction descriptions");
- }
- setDirectionDescriptionsResourceId(resourceId);
- }
-
- a.recycle();
-
- // Use gravity attribute from LinearLayout
- a = context.obtainStyledAttributes(attrs, android.R.styleable.LinearLayout);
- mGravity = a.getInt(android.R.styleable.LinearLayout_gravity, Gravity.TOP);
- a.recycle();
-
- setVibrateEnabled(mVibrationDuration > 0);
- assignDefaultsIfNeeded();
- }
-
- private void dump() {
- Log.v(TAG, "Outer Radius = " + mOuterRadius);
- Log.v(TAG, "SnapMargin = " + mSnapMargin);
- Log.v(TAG, "FeedbackCount = " + mFeedbackCount);
- Log.v(TAG, "VibrationDuration = " + mVibrationDuration);
- Log.v(TAG, "TapRadius = " + mTapRadius);
- Log.v(TAG, "WaveCenterX = " + mWaveCenterX);
- Log.v(TAG, "WaveCenterY = " + mWaveCenterY);
- }
-
- public void suspendAnimations() {
- mChevronAnimations.setSuspended(true);
- mTargetAnimations.setSuspended(true);
- mHandleAnimations.setSuspended(true);
- }
-
- public void resumeAnimations() {
- mChevronAnimations.setSuspended(false);
- mTargetAnimations.setSuspended(false);
- mHandleAnimations.setSuspended(false);
- mChevronAnimations.start();
- mTargetAnimations.start();
- mHandleAnimations.start();
- }
-
- @Override
- protected int getSuggestedMinimumWidth() {
- // View should be large enough to contain the background + handle and
- // target drawable on either edge.
- return (int) (Math.max(mOuterRing.getWidth(), 2 * mOuterRadius) + mMaxTargetWidth);
- }
-
- @Override
- protected int getSuggestedMinimumHeight() {
- // View should be large enough to contain the unlock ring + target and
- // target drawable on either edge
- return (int) (Math.max(mOuterRing.getHeight(), 2 * mOuterRadius) + mMaxTargetHeight);
- }
-
- private int resolveMeasured(int measureSpec, int desired)
- {
- int result = 0;
- int specSize = MeasureSpec.getSize(measureSpec);
- switch (MeasureSpec.getMode(measureSpec)) {
- case MeasureSpec.UNSPECIFIED:
- result = desired;
- break;
- case MeasureSpec.AT_MOST:
- result = Math.min(specSize, desired);
- break;
- case MeasureSpec.EXACTLY:
- default:
- result = specSize;
- }
- return result;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- final int minimumWidth = getSuggestedMinimumWidth();
- final int minimumHeight = getSuggestedMinimumHeight();
- int computedWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
- int computedHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
- computeInsets((computedWidth - minimumWidth), (computedHeight - minimumHeight));
- setMeasuredDimension(computedWidth, computedHeight);
- }
-
- private void switchToState(int state, float x, float y) {
- switch (state) {
- case STATE_IDLE:
- deactivateTargets();
- hideTargets(true, false);
- startBackgroundAnimation(0, 0.0f);
- mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
- break;
-
- case STATE_START:
- deactivateHandle(0, 0, 1.0f, null);
- startBackgroundAnimation(0, 0.0f);
- break;
-
- case STATE_FIRST_TOUCH:
- deactivateTargets();
- showTargets(true);
- mHandleDrawable.setState(TargetDrawable.STATE_ACTIVE);
- startBackgroundAnimation(INITIAL_SHOW_HANDLE_DURATION, 1.0f);
- setGrabbedState(OnTriggerListener.CENTER_HANDLE);
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- announceTargets();
- }
- break;
-
- case STATE_TRACKING:
- break;
-
- case STATE_SNAP:
- break;
-
- case STATE_FINISH:
- doFinish();
- break;
- }
- }
-
- private void activateHandle(int duration, int delay, float finalAlpha,
- AnimatorListener finishListener) {
- mHandleAnimations.cancel();
- mHandleAnimations.add(Tweener.to(mHandleDrawable, duration,
- "ease", Ease.Cubic.easeIn,
- "delay", delay,
- "alpha", finalAlpha,
- "onUpdate", mUpdateListener,
- "onComplete", finishListener));
- mHandleAnimations.start();
- }
-
- private void deactivateHandle(int duration, int delay, float finalAlpha,
- AnimatorListener finishListener) {
- mHandleAnimations.cancel();
- mHandleAnimations.add(Tweener.to(mHandleDrawable, duration,
- "ease", Ease.Quart.easeOut,
- "delay", delay,
- "alpha", finalAlpha,
- "x", 0,
- "y", 0,
- "onUpdate", mUpdateListener,
- "onComplete", finishListener));
- mHandleAnimations.start();
- }
-
- /**
- * Animation used to attract user's attention to the target button.
- * Assumes mChevronDrawables is an a list with an even number of chevrons filled with
- * mFeedbackCount items in the order: left, right, top, bottom.
- */
- private void startChevronAnimation() {
- final float chevronStartDistance = mHandleDrawable.getWidth() * 0.8f;
- final float chevronStopDistance = mOuterRadius * 0.9f / 2.0f;
- final float startScale = 0.5f;
- final float endScale = 2.0f;
- final int directionCount = mFeedbackCount > 0 ? mChevronDrawables.size()/mFeedbackCount : 0;
-
- mChevronAnimations.stop();
-
- // Add an animation for all chevron drawables. There are mFeedbackCount drawables
- // in each direction and directionCount directions.
- for (int direction = 0; direction < directionCount; direction++) {
- double angle = 2.0 * Math.PI * direction / directionCount;
- final float sx = (float) Math.cos(angle);
- final float sy = 0.0f - (float) Math.sin(angle);
- final float[] xrange = new float[]
- {sx * chevronStartDistance, sx * chevronStopDistance};
- final float[] yrange = new float[]
- {sy * chevronStartDistance, sy * chevronStopDistance};
- for (int count = 0; count < mFeedbackCount; count++) {
- int delay = count * CHEVRON_INCREMENTAL_DELAY;
- final TargetDrawable icon = mChevronDrawables.get(direction*mFeedbackCount + count);
- if (icon == null) {
- continue;
- }
- mChevronAnimations.add(Tweener.to(icon, CHEVRON_ANIMATION_DURATION,
- "ease", mChevronAnimationInterpolator,
- "delay", delay,
- "x", xrange,
- "y", yrange,
- "alpha", new float[] {1.0f, 0.0f},
- "scaleX", new float[] {startScale, endScale},
- "scaleY", new float[] {startScale, endScale},
- "onUpdate", mUpdateListener));
- }
- }
- mChevronAnimations.start();
- }
-
- private void deactivateTargets() {
- final int count = mTargetDrawables.size();
- for (int i = 0; i < count; i++) {
- TargetDrawable target = mTargetDrawables.get(i);
- target.setState(TargetDrawable.STATE_INACTIVE);
- }
- mActiveTarget = -1;
- }
-
- void invalidateGlobalRegion(TargetDrawable drawable) {
- int width = drawable.getWidth();
- int height = drawable.getHeight();
- RectF childBounds = new RectF(0, 0, width, height);
- childBounds.offset(drawable.getX() - width/2, drawable.getY() - height/2);
- View view = this;
- while (view.getParent() != null && view.getParent() instanceof View) {
- view = (View) view.getParent();
- view.getMatrix().mapRect(childBounds);
- view.invalidate((int) Math.floor(childBounds.left),
- (int) Math.floor(childBounds.top),
- (int) Math.ceil(childBounds.right),
- (int) Math.ceil(childBounds.bottom));
- }
- }
-
- /**
- * Dispatches a trigger event to listener. Ignored if a listener is not set.
- * @param whichTarget the target that was triggered.
- */
- private void dispatchTriggerEvent(int whichTarget) {
- vibrate();
- if (mOnTriggerListener != null) {
- mOnTriggerListener.onTrigger(this, whichTarget);
- }
- }
-
- private void dispatchOnFinishFinalAnimation() {
- if (mOnTriggerListener != null) {
- mOnTriggerListener.onFinishFinalAnimation();
- }
- }
-
- private void doFinish() {
- final int activeTarget = mActiveTarget;
- final boolean targetHit = activeTarget != -1;
-
- if (targetHit) {
- if (DEBUG) Log.v(TAG, "Finish with target hit = " + targetHit);
-
- highlightSelected(activeTarget);
-
- // Inform listener of any active targets. Typically only one will be active.
- deactivateHandle(RETURN_TO_HOME_DURATION, RETURN_TO_HOME_DELAY, 0.0f, mResetListener);
- dispatchTriggerEvent(activeTarget);
- if (!mAlwaysTrackFinger) {
- // Force ring and targets to finish animation to final expanded state
- mTargetAnimations.stop();
- }
- } else {
- // Animate handle back to the center based on current state.
- deactivateHandle(HIDE_ANIMATION_DURATION, HIDE_ANIMATION_DELAY, 1.0f,
- mResetListenerWithPing);
- hideTargets(true, false);
- }
-
- setGrabbedState(OnTriggerListener.NO_HANDLE);
- }
-
- private void highlightSelected(int activeTarget) {
- // Highlight the given target and fade others
- mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
- hideUnselected(activeTarget);
- }
-
- private void hideUnselected(int active) {
- for (int i = 0; i < mTargetDrawables.size(); i++) {
- if (i != active) {
- mTargetDrawables.get(i).setAlpha(0.0f);
- }
- }
- }
-
- private void hideTargets(boolean animate, boolean expanded) {
- mTargetAnimations.cancel();
- // Note: these animations should complete at the same time so that we can swap out
- // the target assets asynchronously from the setTargetResources() call.
- mAnimatingTargets = animate;
- final int duration = animate ? HIDE_ANIMATION_DURATION : 0;
- final int delay = animate ? HIDE_ANIMATION_DELAY : 0;
-
- final float targetScale = expanded ? TARGET_SCALE_EXPANDED : TARGET_SCALE_COLLAPSED;
- final int length = mTargetDrawables.size();
- for (int i = 0; i < length; i++) {
- TargetDrawable target = mTargetDrawables.get(i);
- target.setState(TargetDrawable.STATE_INACTIVE);
- mTargetAnimations.add(Tweener.to(target, duration,
- "ease", Ease.Cubic.easeOut,
- "alpha", 0.0f,
- "scaleX", targetScale,
- "scaleY", targetScale,
- "delay", delay,
- "onUpdate", mUpdateListener));
- }
-
- final float ringScaleTarget = expanded ? RING_SCALE_EXPANDED : RING_SCALE_COLLAPSED;
- mTargetAnimations.add(Tweener.to(mOuterRing, duration,
- "ease", Ease.Cubic.easeOut,
- "alpha", 0.0f,
- "scaleX", ringScaleTarget,
- "scaleY", ringScaleTarget,
- "delay", delay,
- "onUpdate", mUpdateListener,
- "onComplete", mTargetUpdateListener));
-
- mTargetAnimations.start();
- }
-
- private void showTargets(boolean animate) {
- mTargetAnimations.stop();
- mAnimatingTargets = animate;
- final int delay = animate ? SHOW_ANIMATION_DELAY : 0;
- final int duration = animate ? SHOW_ANIMATION_DURATION : 0;
- final int length = mTargetDrawables.size();
- for (int i = 0; i < length; i++) {
- TargetDrawable target = mTargetDrawables.get(i);
- target.setState(TargetDrawable.STATE_INACTIVE);
- mTargetAnimations.add(Tweener.to(target, duration,
- "ease", Ease.Cubic.easeOut,
- "alpha", 1.0f,
- "scaleX", 1.0f,
- "scaleY", 1.0f,
- "delay", delay,
- "onUpdate", mUpdateListener));
- }
- mTargetAnimations.add(Tweener.to(mOuterRing, duration,
- "ease", Ease.Cubic.easeOut,
- "alpha", 1.0f,
- "scaleX", 1.0f,
- "scaleY", 1.0f,
- "delay", delay,
- "onUpdate", mUpdateListener,
- "onComplete", mTargetUpdateListener));
-
- mTargetAnimations.start();
- }
-
- private void vibrate() {
- final boolean hapticEnabled = Settings.System.getIntForUser(
- mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ENABLED, 1,
- UserHandle.USER_CURRENT) != 0;
- if (mVibrator != null && hapticEnabled) {
- mVibrator.vibrate(mVibrationDuration, AudioManager.STREAM_SYSTEM);
- }
- }
-
- private ArrayList<TargetDrawable> loadDrawableArray(int resourceId) {
- Resources res = getContext().getResources();
- TypedArray array = res.obtainTypedArray(resourceId);
- final int count = array.length();
- ArrayList<TargetDrawable> drawables = new ArrayList<TargetDrawable>(count);
- for (int i = 0; i < count; i++) {
- TypedValue value = array.peekValue(i);
- TargetDrawable target = new TargetDrawable(res, value != null ? value.resourceId : 0);
- drawables.add(target);
- }
- array.recycle();
- return drawables;
- }
-
- private void internalSetTargetResources(int resourceId) {
- mTargetDrawables = loadDrawableArray(resourceId);
- mTargetResourceId = resourceId;
- final int count = mTargetDrawables.size();
- int maxWidth = mHandleDrawable.getWidth();
- int maxHeight = mHandleDrawable.getHeight();
- for (int i = 0; i < count; i++) {
- TargetDrawable target = mTargetDrawables.get(i);
- maxWidth = Math.max(maxWidth, target.getWidth());
- maxHeight = Math.max(maxHeight, target.getHeight());
- }
- if (mMaxTargetWidth != maxWidth || mMaxTargetHeight != maxHeight) {
- mMaxTargetWidth = maxWidth;
- mMaxTargetHeight = maxHeight;
- requestLayout(); // required to resize layout and call updateTargetPositions()
- } else {
- updateTargetPositions(mWaveCenterX, mWaveCenterY);
- updateChevronPositions(mWaveCenterX, mWaveCenterY);
- }
- }
-
- /**
- * Loads an array of drawables from the given resourceId.
- *
- * @param resourceId
- */
- public void setTargetResources(int resourceId) {
- if (mAnimatingTargets) {
- // postpone this change until we return to the initial state
- mNewTargetResources = resourceId;
- } else {
- internalSetTargetResources(resourceId);
- }
- }
-
- public int getTargetResourceId() {
- return mTargetResourceId;
- }
-
- /**
- * Sets the resource id specifying the target descriptions for accessibility.
- *
- * @param resourceId The resource id.
- */
- public void setTargetDescriptionsResourceId(int resourceId) {
- mTargetDescriptionsResourceId = resourceId;
- if (mTargetDescriptions != null) {
- mTargetDescriptions.clear();
- }
- }
-
- /**
- * Gets the resource id specifying the target descriptions for accessibility.
- *
- * @return The resource id.
- */
- public int getTargetDescriptionsResourceId() {
- return mTargetDescriptionsResourceId;
- }
-
- /**
- * Sets the resource id specifying the target direction descriptions for accessibility.
- *
- * @param resourceId The resource id.
- */
- public void setDirectionDescriptionsResourceId(int resourceId) {
- mDirectionDescriptionsResourceId = resourceId;
- if (mDirectionDescriptions != null) {
- mDirectionDescriptions.clear();
- }
- }
-
- /**
- * Gets the resource id specifying the target direction descriptions.
- *
- * @return The resource id.
- */
- public int getDirectionDescriptionsResourceId() {
- return mDirectionDescriptionsResourceId;
- }
-
- /**
- * Enable or disable vibrate on touch.
- *
- * @param enabled
- */
- public void setVibrateEnabled(boolean enabled) {
- if (enabled && mVibrator == null) {
- mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
- } else {
- mVibrator = null;
- }
- }
-
- /**
- * Starts chevron animation. Example use case: show chevron animation whenever the phone rings
- * or the user touches the screen.
- *
- */
- public void ping() {
- startChevronAnimation();
- }
-
- /**
- * Resets the widget to default state and cancels all animation. If animate is 'true', will
- * animate objects into place. Otherwise, objects will snap back to place.
- *
- * @param animate
- */
- public void reset(boolean animate) {
- mChevronAnimations.stop();
- mHandleAnimations.stop();
- mTargetAnimations.stop();
- startBackgroundAnimation(0, 0.0f);
- hideChevrons();
- hideTargets(animate, false);
- deactivateHandle(0, 0, 1.0f, null);
- Tweener.reset();
- }
-
- private void startBackgroundAnimation(int duration, float alpha) {
- Drawable background = getBackground();
- if (mAlwaysTrackFinger && background != null) {
- if (mBackgroundAnimator != null) {
- mBackgroundAnimator.animator.end();
- }
- mBackgroundAnimator = Tweener.to(background, duration,
- "ease", Ease.Cubic.easeIn,
- "alpha", new int[] {0, (int)(255.0f * alpha)},
- "delay", SHOW_ANIMATION_DELAY);
- mBackgroundAnimator.animator.start();
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- final int action = event.getAction();
- boolean handled = false;
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- if (DEBUG) Log.v(TAG, "*** DOWN ***");
- handleDown(event);
- handled = true;
- break;
-
- case MotionEvent.ACTION_MOVE:
- if (DEBUG) Log.v(TAG, "*** MOVE ***");
- handleMove(event);
- handled = true;
- break;
-
- case MotionEvent.ACTION_UP:
- if (DEBUG) Log.v(TAG, "*** UP ***");
- handleMove(event);
- handleUp(event);
- handled = true;
- break;
-
- case MotionEvent.ACTION_CANCEL:
- if (DEBUG) Log.v(TAG, "*** CANCEL ***");
- handleMove(event);
- handleCancel(event);
- handled = true;
- break;
- }
- invalidate();
- return handled ? true : super.onTouchEvent(event);
- }
-
- private void moveHandleTo(float x, float y, boolean animate) {
- mHandleDrawable.setX(x);
- mHandleDrawable.setY(y);
- }
-
- private void handleDown(MotionEvent event) {
- float eventX = event.getX();
- float eventY = event.getY();
- switchToState(STATE_START, eventX, eventY);
- if (!trySwitchToFirstTouchState(eventX, eventY)) {
- mDragging = false;
- ping();
- }
- }
-
- private void handleUp(MotionEvent event) {
- if (DEBUG && mDragging) Log.v(TAG, "** Handle RELEASE");
- switchToState(STATE_FINISH, event.getX(), event.getY());
- }
-
- private void handleCancel(MotionEvent event) {
- if (DEBUG && mDragging) Log.v(TAG, "** Handle CANCEL");
-
- // We should drop the active target here but it interferes with
- // moving off the screen in the direction of the navigation bar. At some point we may
- // want to revisit how we handle this. For now we'll allow a canceled event to
- // activate the current target.
-
- // mActiveTarget = -1; // Drop the active target if canceled.
-
- switchToState(STATE_FINISH, event.getX(), event.getY());
- }
-
- private void handleMove(MotionEvent event) {
- int activeTarget = -1;
- final int historySize = event.getHistorySize();
- ArrayList<TargetDrawable> targets = mTargetDrawables;
- int ntargets = targets.size();
- float x = 0.0f;
- float y = 0.0f;
- for (int k = 0; k < historySize + 1; k++) {
- float eventX = k < historySize ? event.getHistoricalX(k) : event.getX();
- float eventY = k < historySize ? event.getHistoricalY(k) : event.getY();
- // tx and ty are relative to wave center
- float tx = eventX - mWaveCenterX;
- float ty = eventY - mWaveCenterY;
- float touchRadius = (float) Math.sqrt(dist2(tx, ty));
- final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f;
- float limitX = tx * scale;
- float limitY = ty * scale;
- double angleRad = Math.atan2(-ty, tx);
-
- if (!mDragging) {
- trySwitchToFirstTouchState(eventX, eventY);
- }
-
- if (mDragging) {
- // For multiple targets, snap to the one that matches
- final float snapRadius = mOuterRadius - mSnapMargin;
- final float snapDistance2 = snapRadius * snapRadius;
- // Find first target in range
- for (int i = 0; i < ntargets; i++) {
- TargetDrawable target = targets.get(i);
-
- double targetMinRad = (i - 0.5) * 2 * Math.PI / ntargets;
- double targetMaxRad = (i + 0.5) * 2 * Math.PI / ntargets;
- if (target.isEnabled()) {
- boolean angleMatches =
- (angleRad > targetMinRad && angleRad <= targetMaxRad) ||
- (angleRad + 2 * Math.PI > targetMinRad &&
- angleRad + 2 * Math.PI <= targetMaxRad);
- if (angleMatches && (dist2(tx, ty) > snapDistance2)) {
- activeTarget = i;
- }
- }
- }
- }
- x = limitX;
- y = limitY;
- }
-
- if (!mDragging) {
- return;
- }
-
- if (activeTarget != -1) {
- switchToState(STATE_SNAP, x,y);
- moveHandleTo(x, y, false);
- } else {
- switchToState(STATE_TRACKING, x, y);
- moveHandleTo(x, y, false);
- }
-
- // Draw handle outside parent's bounds
- invalidateGlobalRegion(mHandleDrawable);
-
- if (mActiveTarget != activeTarget) {
- // Defocus the old target
- if (mActiveTarget != -1) {
- TargetDrawable target = targets.get(mActiveTarget);
- if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
- target.setState(TargetDrawable.STATE_INACTIVE);
- }
- }
- // Focus the new target
- if (activeTarget != -1) {
- TargetDrawable target = targets.get(activeTarget);
- if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
- target.setState(TargetDrawable.STATE_FOCUSED);
- }
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- String targetContentDescription = getTargetDescription(activeTarget);
- announceText(targetContentDescription);
- }
- activateHandle(0, 0, 0.0f, null);
- } else {
- activateHandle(0, 0, 1.0f, null);
- }
- }
- mActiveTarget = activeTarget;
- }
-
- @Override
- public boolean onHoverEvent(MotionEvent event) {
- if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
- final int action = event.getAction();
- switch (action) {
- case MotionEvent.ACTION_HOVER_ENTER:
- event.setAction(MotionEvent.ACTION_DOWN);
- break;
- case MotionEvent.ACTION_HOVER_MOVE:
- event.setAction(MotionEvent.ACTION_MOVE);
- break;
- case MotionEvent.ACTION_HOVER_EXIT:
- event.setAction(MotionEvent.ACTION_UP);
- break;
- }
- onTouchEvent(event);
- event.setAction(action);
- }
- return super.onHoverEvent(event);
- }
-
- /**
- * Sets the current grabbed state, and dispatches a grabbed state change
- * event to our listener.
- */
- private void setGrabbedState(int newState) {
- if (newState != mGrabbedState) {
- if (newState != OnTriggerListener.NO_HANDLE) {
- vibrate();
- }
- mGrabbedState = newState;
- if (mOnTriggerListener != null) {
- if (newState == OnTriggerListener.NO_HANDLE) {
- mOnTriggerListener.onReleased(this, OnTriggerListener.CENTER_HANDLE);
- } else {
- mOnTriggerListener.onGrabbed(this, OnTriggerListener.CENTER_HANDLE);
- }
- mOnTriggerListener.onGrabbedStateChange(this, newState);
- }
- }
- }
-
- private boolean trySwitchToFirstTouchState(float x, float y) {
- final float tx = x - mWaveCenterX;
- final float ty = y - mWaveCenterY;
- if (mAlwaysTrackFinger || dist2(tx,ty) <= getScaledTapRadiusSquared()) {
- if (DEBUG) Log.v(TAG, "** Handle HIT");
- switchToState(STATE_FIRST_TOUCH, x, y);
- moveHandleTo(tx, ty, false);
- mDragging = true;
- return true;
- }
- return false;
- }
-
- private void assignDefaultsIfNeeded() {
- if (mOuterRadius == 0.0f) {
- mOuterRadius = Math.max(mOuterRing.getWidth(), mOuterRing.getHeight())/2.0f;
- }
- if (mSnapMargin == 0.0f) {
- mSnapMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- SNAP_MARGIN_DEFAULT, getContext().getResources().getDisplayMetrics());
- }
- }
-
- private void computeInsets(int dx, int dy) {
- final int layoutDirection = getLayoutDirection();
- final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
-
- switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- mHorizontalInset = 0;
- break;
- case Gravity.RIGHT:
- mHorizontalInset = dx;
- break;
- case Gravity.CENTER_HORIZONTAL:
- default:
- mHorizontalInset = dx / 2;
- break;
- }
- switch (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) {
- case Gravity.TOP:
- mVerticalInset = 0;
- break;
- case Gravity.BOTTOM:
- mVerticalInset = dy;
- break;
- case Gravity.CENTER_VERTICAL:
- default:
- mVerticalInset = dy / 2;
- break;
- }
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- final int width = right - left;
- final int height = bottom - top;
-
- // Target placement width/height. This puts the targets on the greater of the ring
- // width or the specified outer radius.
- final float placementWidth = Math.max(mOuterRing.getWidth(), 2 * mOuterRadius);
- final float placementHeight = Math.max(mOuterRing.getHeight(), 2 * mOuterRadius);
- float newWaveCenterX = mHorizontalInset
- + Math.max(width, mMaxTargetWidth + placementWidth) / 2;
- float newWaveCenterY = mVerticalInset
- + Math.max(height, + mMaxTargetHeight + placementHeight) / 2;
-
- if (mInitialLayout) {
- hideChevrons();
- hideTargets(false, false);
- moveHandleTo(0, 0, false);
- mInitialLayout = false;
- }
-
- mOuterRing.setPositionX(newWaveCenterX);
- mOuterRing.setPositionY(newWaveCenterY);
-
- mHandleDrawable.setPositionX(newWaveCenterX);
- mHandleDrawable.setPositionY(newWaveCenterY);
-
- updateTargetPositions(newWaveCenterX, newWaveCenterY);
- updateChevronPositions(newWaveCenterX, newWaveCenterY);
-
- mWaveCenterX = newWaveCenterX;
- mWaveCenterY = newWaveCenterY;
-
- if (DEBUG) dump();
- }
-
- private void updateTargetPositions(float centerX, float centerY) {
- // Reposition the target drawables if the view changed.
- ArrayList<TargetDrawable> targets = mTargetDrawables;
- final int size = targets.size();
- final float alpha = (float) (-2.0f * Math.PI / size);
- for (int i = 0; i < size; i++) {
- final TargetDrawable targetIcon = targets.get(i);
- final float angle = alpha * i;
- targetIcon.setPositionX(centerX);
- targetIcon.setPositionY(centerY);
- targetIcon.setX(mOuterRadius * (float) Math.cos(angle));
- targetIcon.setY(mOuterRadius * (float) Math.sin(angle));
- }
- }
-
- private void updateChevronPositions(float centerX, float centerY) {
- ArrayList<TargetDrawable> chevrons = mChevronDrawables;
- final int size = chevrons.size();
- for (int i = 0; i < size; i++) {
- TargetDrawable target = chevrons.get(i);
- if (target != null) {
- target.setPositionX(centerX);
- target.setPositionY(centerY);
- }
- }
- }
-
- private void hideChevrons() {
- ArrayList<TargetDrawable> chevrons = mChevronDrawables;
- final int size = chevrons.size();
- for (int i = 0; i < size; i++) {
- TargetDrawable chevron = chevrons.get(i);
- if (chevron != null) {
- chevron.setAlpha(0.0f);
- }
- }
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- mOuterRing.draw(canvas);
- final int ntargets = mTargetDrawables.size();
- for (int i = 0; i < ntargets; i++) {
- TargetDrawable target = mTargetDrawables.get(i);
- if (target != null) {
- target.draw(canvas);
- }
- }
- final int nchevrons = mChevronDrawables.size();
- for (int i = 0; i < nchevrons; i++) {
- TargetDrawable chevron = mChevronDrawables.get(i);
- if (chevron != null) {
- chevron.draw(canvas);
- }
- }
- mHandleDrawable.draw(canvas);
- }
-
- public void setOnTriggerListener(OnTriggerListener listener) {
- mOnTriggerListener = listener;
- }
-
- private float square(float d) {
- return d * d;
- }
-
- private float dist2(float dx, float dy) {
- return dx*dx + dy*dy;
- }
-
- private float getScaledTapRadiusSquared() {
- final float scaledTapRadius;
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- scaledTapRadius = TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED * mTapRadius;
- } else {
- scaledTapRadius = mTapRadius;
- }
- return square(scaledTapRadius);
- }
-
- private void announceTargets() {
- StringBuilder utterance = new StringBuilder();
- final int targetCount = mTargetDrawables.size();
- for (int i = 0; i < targetCount; i++) {
- String targetDescription = getTargetDescription(i);
- String directionDescription = getDirectionDescription(i);
- if (!TextUtils.isEmpty(targetDescription)
- && !TextUtils.isEmpty(directionDescription)) {
- String text = String.format(directionDescription, targetDescription);
- utterance.append(text);
- }
- if (utterance.length() > 0) {
- announceText(utterance.toString());
- }
- }
- }
-
- private void announceText(String text) {
- setContentDescription(text);
- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
- setContentDescription(null);
- }
-
- private String getTargetDescription(int index) {
- if (mTargetDescriptions == null || mTargetDescriptions.isEmpty()) {
- mTargetDescriptions = loadDescriptions(mTargetDescriptionsResourceId);
- if (mTargetDrawables.size() != mTargetDescriptions.size()) {
- Log.w(TAG, "The number of target drawables must be"
- + " euqal to the number of target descriptions.");
- return null;
- }
- }
- return mTargetDescriptions.get(index);
- }
-
- private String getDirectionDescription(int index) {
- if (mDirectionDescriptions == null || mDirectionDescriptions.isEmpty()) {
- mDirectionDescriptions = loadDescriptions(mDirectionDescriptionsResourceId);
- if (mTargetDrawables.size() != mDirectionDescriptions.size()) {
- Log.w(TAG, "The number of target drawables must be"
- + " euqal to the number of direction descriptions.");
- return null;
- }
- }
- return mDirectionDescriptions.get(index);
- }
-
- private ArrayList<String> loadDescriptions(int resourceId) {
- TypedArray array = getContext().getResources().obtainTypedArray(resourceId);
- final int count = array.length();
- ArrayList<String> targetContentDescriptions = new ArrayList<String>(count);
- for (int i = 0; i < count; i++) {
- String contentDescription = array.getString(i);
- targetContentDescriptions.add(contentDescription);
- }
- array.recycle();
- return targetContentDescriptions;
- }
-
- public int getResourceIdForTarget(int index) {
- final TargetDrawable drawable = mTargetDrawables.get(index);
- return drawable == null ? 0 : drawable.getResourceId();
- }
-
- public void setEnableTarget(int resourceId, boolean enabled) {
- for (int i = 0; i < mTargetDrawables.size(); i++) {
- final TargetDrawable target = mTargetDrawables.get(i);
- if (target.getResourceId() == resourceId) {
- target.setEnabled(enabled);
- break; // should never be more than one match
- }
- }
- }
-
- /**
- * Gets the position of a target in the array that matches the given resource.
- * @param resourceId
- * @return the index or -1 if not found
- */
- public int getTargetPosition(int resourceId) {
- for (int i = 0; i < mTargetDrawables.size(); i++) {
- final TargetDrawable target = mTargetDrawables.get(i);
- if (target.getResourceId() == resourceId) {
- return i; // should never be more than one match
- }
- }
- return -1;
- }
-
- private boolean replaceTargetDrawables(Resources res, int existingResourceId,
- int newResourceId) {
- if (existingResourceId == 0 || newResourceId == 0) {
- return false;
- }
-
- boolean result = false;
- final ArrayList<TargetDrawable> drawables = mTargetDrawables;
- final int size = drawables.size();
- for (int i = 0; i < size; i++) {
- final TargetDrawable target = drawables.get(i);
- if (target != null && target.getResourceId() == existingResourceId) {
- target.setDrawable(res, newResourceId);
- result = true;
- }
- }
-
- if (result) {
- requestLayout(); // in case any given drawable's size changes
- }
-
- return result;
- }
-
- /**
- * Searches the given package for a resource to use to replace the Drawable on the
- * target with the given resource id
- * @param component of the .apk that contains the resource
- * @param name of the metadata in the .apk
- * @param existingResId the resource id of the target to search for
- * @return true if found in the given package and replaced at least one target Drawables
- */
- public boolean replaceTargetDrawablesIfPresent(ComponentName component, String name,
- int existingResId) {
- if (existingResId == 0) return false;
-
- try {
- PackageManager packageManager = mContext.getPackageManager();
- // Look for the search icon specified in the activity meta-data
- Bundle metaData = packageManager.getActivityInfo(
- component, PackageManager.GET_META_DATA).metaData;
- if (metaData != null) {
- int iconResId = metaData.getInt(name);
- if (iconResId != 0) {
- Resources res = packageManager.getResourcesForActivity(component);
- return replaceTargetDrawables(res, existingResId, iconResId);
- }
- }
- } catch (NameNotFoundException e) {
- Log.w(TAG, "Failed to swap drawable; "
- + component.flattenToShortString() + " not found", e);
- } catch (Resources.NotFoundException nfe) {
- Log.w(TAG, "Failed to swap drawable from "
- + component.flattenToShortString(), nfe);
- }
- return false;
- }
-}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 51c5a86..711f28a 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -151,7 +151,8 @@
android_content_res_ObbScanner.cpp \
android_content_res_Configuration.cpp \
android_animation_PropertyValuesHolder.cpp \
- com_android_internal_net_NetworkStatsFactory.cpp
+ com_android_internal_net_NetworkStatsFactory.cpp \
+ com_android_internal_os_Zygote.cpp
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
@@ -177,7 +178,8 @@
external/harfbuzz_ng/src \
external/zlib \
frameworks/opt/emoji \
- libcore/include
+ libcore/include \
+ $(call include-path-for, audio-utils) \
LOCAL_SHARED_LIBRARIES := \
libmemtrack \
@@ -213,7 +215,8 @@
libjpeg \
libusbhost \
libharfbuzz_ng \
- libz
+ libz \
+ libaudioutils \
ifeq ($(USE_OPENGL_RENDERER),true)
LOCAL_SHARED_LIBRARIES += libhwui
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 9a7a5f9..4759451 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -178,6 +178,7 @@
extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
extern int register_com_android_internal_net_NetworkStatsFactory(JNIEnv *env);
+extern int register_com_android_internal_os_Zygote(JNIEnv *env);
static AndroidRuntime* gCurRuntime = NULL;
@@ -228,9 +229,10 @@
/*static*/ JavaVM* AndroidRuntime::mJavaVM = NULL;
-
-AndroidRuntime::AndroidRuntime() :
- mExitWithoutCleanup(false)
+AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
+ mExitWithoutCleanup(false),
+ mArgBlockStart(argBlockStart),
+ mArgBlockLength(argBlockLength)
{
SkGraphics::Init();
// this sets our preference for 16bit images during decode
@@ -265,6 +267,10 @@
return jniRegisterNativeMethods(env, className, gMethods, numMethods);
}
+void AndroidRuntime::setArgv0(const char* argv0) {
+ strlcpy(mArgBlockStart, argv0, mArgBlockLength);
+}
+
status_t AndroidRuntime::callMain(const char* className,
jclass clazz, int argc, const char* const argv[])
{
@@ -1244,6 +1250,7 @@
REG_JNI(register_android_net_TrafficStats),
REG_JNI(register_android_os_MemoryFile),
REG_JNI(register_com_android_internal_os_ZygoteInit),
+ REG_JNI(register_com_android_internal_os_Zygote),
REG_JNI(register_android_hardware_Camera),
REG_JNI(register_android_hardware_camera2_CameraMetadata),
REG_JNI(register_android_hardware_SensorManager),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 2b9a5c4..b89dced 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -7,6 +7,7 @@
#include "SkImageDecoder.h"
#include "SkImageRef_ashmem.h"
#include "SkImageRef_GlobalPool.h"
+#include "SkMath.h"
#include "SkPixelRef.h"
#include "SkStream.h"
#include "SkTemplates.h"
@@ -146,15 +147,15 @@
return pr;
}
-static SkBitmap::Config configForScaledOutput(SkBitmap::Config config) {
- switch (config) {
- case SkBitmap::kNo_Config:
- case SkBitmap::kIndex8_Config:
- return SkBitmap::kARGB_8888_Config;
+static SkColorType colorTypeForScaledOutput(SkColorType colorType) {
+ switch (colorType) {
+ case kUnknown_SkColorType:
+ case kIndex_8_SkColorType:
+ return kPMColor_SkColorType;
default:
break;
}
- return config;
+ return colorType;
}
class ScaleCheckingAllocator : public SkBitmap::HeapAllocator {
@@ -165,8 +166,8 @@
virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
// accounts for scale in final allocation, using eventual size and config
- const int bytesPerPixel = SkBitmap::ComputeBytesPerPixel(
- configForScaledOutput(bitmap->config()));
+ const int bytesPerPixel = SkColorTypeBytesPerPixel(
+ colorTypeForScaledOutput(bitmap->colorType()));
const int requestedSize = bytesPerPixel *
int(bitmap->width() * mScale + 0.5f) *
int(bitmap->height() * mScale + 0.5f);
@@ -194,21 +195,28 @@
}
virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
- if (!bitmap->getSize64().is32() || bitmap->getSize() > mSize) {
- ALOGW("bitmap marked for reuse (%d bytes) can't fit new bitmap (%d bytes)",
- mSize, bitmap->getSize());
+ const SkImageInfo& info = bitmap->info();
+ if (info.fColorType == kUnknown_SkColorType) {
+ ALOGW("unable to reuse a bitmap as the target has an unknown bitmap configuration");
return false;
}
- SkImageInfo bitmapInfo;
- if (!bitmap->asImageInfo(&bitmapInfo)) {
- ALOGW("unable to reuse a bitmap as the target has an unknown bitmap configuration");
+ const int64_t size64 = info.getSafeSize64(bitmap->rowBytes());
+ if (!sk_64_isS32(size64)) {
+ ALOGW("bitmap is too large");
+ return false;
+ }
+
+ const size_t size = sk_64_asS32(size64);
+ if (size > mSize) {
+ ALOGW("bitmap marked for reuse (%d bytes) can't fit new bitmap (%d bytes)",
+ mSize, size);
return false;
}
// Create a new pixelref with the new ctable that wraps the previous pixelref
SkPixelRef* pr = new AndroidPixelRef(*static_cast<AndroidPixelRef*>(mPixelRef),
- bitmapInfo, bitmap->rowBytes(), ctable);
+ info, bitmap->rowBytes(), ctable);
bitmap->setPixelRef(pr)->unref();
// since we're already allocated, we lockPixels right away
@@ -416,12 +424,12 @@
const float sy = scaledHeight / float(decodingBitmap.height());
// TODO: avoid copying when scaled size equals decodingBitmap size
- SkBitmap::Config config = configForScaledOutput(decodingBitmap.config());
+ SkColorType colorType = colorTypeForScaledOutput(decodingBitmap.colorType());
// FIXME: If the alphaType is kUnpremul and the image has alpha, the
// colors may not be correct, since Skia does not yet support drawing
// to/from unpremultiplied bitmaps.
- outputBitmap->setConfig(config, scaledWidth, scaledHeight, 0,
- decodingBitmap.alphaType());
+ outputBitmap->setConfig(SkImageInfo::Make(scaledWidth, scaledHeight,
+ colorType, decodingBitmap.alphaType()));
if (!outputBitmap->allocPixels(outputAllocator, NULL)) {
return nullObjectReturn("allocation failed for scaled bitmap");
}
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 7420055..946b898 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -680,9 +680,6 @@
indices [ptCount * sizeof(uint16_t)]
*/
ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
-#ifdef SK_SCALAR_IS_FIXED
- storageSize += ptCount * sizeof(SkPoint); // storage for verts
-#endif
storageSize += indexCount * sizeof(uint16_t); // indices[]
SkAutoMalloc storage(storageSize);
@@ -693,16 +690,7 @@
verts = (SkPoint*)(vertA.ptr() + vertIndex);
indices = (uint16_t*)(texs + ptCount);
#else
- verts = texs + ptCount;
- indices = (uint16_t*)(verts + ptCount);
- // convert floats to fixed
- {
- const float* src = vertA.ptr() + vertIndex;
- for (int i = 0; i < ptCount; i++) {
- verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
- src += 2;
- }
- }
+ SkASSERT(false);
#endif
// cons up texture coordinates and indices
@@ -804,25 +792,7 @@
texs = (SkPoint*)(texA.ptr() + texIndex);
}
#else
- int count = ptCount; // for verts
- if (jtexs != NULL) {
- count += ptCount; // += for texs
- }
- SkAutoMalloc storage(count * sizeof(SkPoint));
- verts = (SkPoint*)storage.get();
- const float* src = vertA.ptr() + vertIndex;
- for (int i = 0; i < ptCount; i++) {
- verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
- src += 2;
- }
- if (jtexs != NULL) {
- texs = verts + ptCount;
- src = texA.ptr() + texIndex;
- for (int i = 0; i < ptCount; i++) {
- texs[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
- src += 2;
- }
- }
+ SkASSERT(false);
#endif
const SkColor* colors = NULL;
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index 09589bd..a59ed19 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -50,14 +50,10 @@
AutoJavaFloatArray autoArray(env, jarray, 20);
const float* src = autoArray.ptr();
-#ifdef SK_SCALAR_IS_FIXED
- SkFixed array[20];
- for (int i = 0; i < 20; i++) {
- array[i] = SkFloatToScalar(src[i]);
- }
- return reinterpret_cast<jlong>(new SkColorMatrixFilter(array));
-#else
+#ifdef SK_SCALAR_IS_FLOAT
return reinterpret_cast<jlong>(new SkColorMatrixFilter(src));
+#else
+ SkASSERT(false);
#endif
}
};
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 98edbdb..2883be9 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -6,6 +6,7 @@
#include "SkCanvas.h"
#include "SkDevice.h"
+#include "SkMath.h"
#include "SkPicture.h"
#include "SkRegion.h"
#include <android_runtime/AndroidRuntime.h>
@@ -564,21 +565,20 @@
jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
SkColorTable* ctable) {
- Sk64 size64 = bitmap->getSize64();
- if (size64.isNeg() || !size64.is32()) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "bitmap size exceeds 32bits");
+ const SkImageInfo& info = bitmap->info();
+ if (info.fColorType == kUnknown_SkColorType) {
+ doThrowIAE(env, "unknown bitmap configuration");
return NULL;
}
- SkImageInfo bitmapInfo;
- if (!bitmap->asImageInfo(&bitmapInfo)) {
- jniThrowException(env, "java/lang/IllegalArgumentException",
- "unknown bitmap configuration");
+ const int64_t size64 = info.getSafeSize64(bitmap->rowBytes());
+ if (!sk_64_isS32(size64)) {
+ doThrowIAE(env, "bitmap size exceeds 32bits");
return NULL;
}
+ const size_t size = sk_64_asS32(size64);
+ SkASSERT(size == info.getSafeSize(bitmap->rowBytes()));
- size_t size = size64.get32();
jbyteArray arrayObj = (jbyteArray) env->CallObjectMethod(gVMRuntime,
gVMRuntime_newNonMovableArray,
gByte_class, size);
@@ -591,7 +591,7 @@
return NULL;
}
SkASSERT(addr);
- SkPixelRef* pr = new AndroidPixelRef(env, bitmapInfo, (void*) addr,
+ SkPixelRef* pr = new AndroidPixelRef(env, info, (void*) addr,
bitmap->rowBytes(), arrayObj, ctable);
bitmap->setPixelRef(pr)->unref();
// since we're already allocated, we lockPixels right away
diff --git a/core/jni/android/graphics/Matrix.cpp b/core/jni/android/graphics/Matrix.cpp
index 6ae9fea..c400c57 100644
--- a/core/jni/android/graphics/Matrix.cpp
+++ b/core/jni/android/graphics/Matrix.cpp
@@ -272,18 +272,11 @@
float* dst = autoDst.ptr() + dstIndex;
bool result;
-#ifdef SK_SCALAR_IS_FIXED
- SkPoint srcPt[4], dstPt[4];
- for (int i = 0; i < ptCount; i++) {
- int x = i << 1;
- int y = x + 1;
- srcPt[i].set(SkFloatToScalar(src[x]), SkFloatToScalar(src[y]));
- dstPt[i].set(SkFloatToScalar(dst[x]), SkFloatToScalar(dst[y]));
- }
- result = matrix->setPolyToPoly(srcPt, dstPt, ptCount);
-#else
+#ifdef SK_SCALAR_IS_FLOAT
result = matrix->setPolyToPoly((const SkPoint*)src, (const SkPoint*)dst,
ptCount);
+#else
+ SkASSERT(false);
#endif
return result ? JNI_TRUE : JNI_FALSE;
}
@@ -304,36 +297,15 @@
AutoJavaFloatArray autoDst(env, dst, dstIndex + (ptCount << 1), kRW_JNIAccess);
float* srcArray = autoSrc.ptr() + srcIndex;
float* dstArray = autoDst.ptr() + dstIndex;
-
-#ifdef SK_SCALAR_IS_FIXED
- // we allocate twice the count, 1 set for src, 1 for dst
- SkAutoSTMalloc<32, SkPoint> storage(ptCount * 2);
- SkPoint* pts = storage.get();
- SkPoint* srcPt = pts;
- SkPoint* dstPt = pts + ptCount;
-
- int i;
- for (i = 0; i < ptCount; i++) {
- srcPt[i].set(SkFloatToScalar(srcArray[i << 1]),
- SkFloatToScalar(srcArray[(i << 1) + 1]));
- }
-
- if (isPts)
- matrix->mapPoints(dstPt, srcPt, ptCount);
- else
- matrix->mapVectors(dstPt, srcPt, ptCount);
-
- for (i = 0; i < ptCount; i++) {
- dstArray[i << 1] = SkScalarToFloat(dstPt[i].fX);
- dstArray[(i << 1) + 1] = SkScalarToFloat(dstPt[i].fY);
- }
-#else
+#ifdef SK_SCALAR_IS_FLOAT
if (isPts)
matrix->mapPoints((SkPoint*)dstArray, (const SkPoint*)srcArray,
ptCount);
else
matrix->mapVectors((SkVector*)dstArray, (const SkVector*)srcArray,
ptCount);
+#else
+ SkASSERT(false);
#endif
}
@@ -356,18 +328,12 @@
SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
AutoJavaFloatArray autoValues(env, values, 9, kRW_JNIAccess);
float* dst = autoValues.ptr();
-
-#ifdef SK_SCALAR_IS_FIXED
- for (int i = 0; i < 6; i++) {
- dst[i] = SkFixedToFloat(matrix->get(i));
- }
- for (int j = 6; j < 9; j++) {
- dst[j] = SkFractToFloat(matrix->get(j));
- }
-#else
+#ifdef SK_SCALAR_IS_FLOAT
for (int i = 0; i < 9; i++) {
dst[i] = matrix->get(i);
}
+#else
+ SkASSERT(false);
#endif
}
@@ -376,17 +342,12 @@
AutoJavaFloatArray autoValues(env, values, 9, kRO_JNIAccess);
const float* src = autoValues.ptr();
-#ifdef SK_SCALAR_IS_FIXED
- for (int i = 0; i < 6; i++) {
- matrix->set(i, SkFloatToFixed(src[i]));
- }
- for (int j = 6; j < 9; j++) {
- matrix->set(j, SkFloatToFract(src[j]));
- }
-#else
+#ifdef SK_SCALAR_IS_FLOAT
for (int i = 0; i < 9; i++) {
matrix->set(i, src[i]);
}
+#else
+ SkASSERT(false);
#endif
}
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 51990d5..1167bfe 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -422,16 +422,16 @@
SkPaint::FontMetrics metrics;
GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
- int ascent = SkScalarRound(metrics.fAscent);
- int descent = SkScalarRound(metrics.fDescent);
- int leading = SkScalarRound(metrics.fLeading);
+ int ascent = SkScalarRoundToInt(metrics.fAscent);
+ int descent = SkScalarRoundToInt(metrics.fDescent);
+ int leading = SkScalarRoundToInt(metrics.fLeading);
if (metricsObj) {
SkASSERT(env->IsInstanceOf(metricsObj, gFontMetricsInt_class));
- env->SetIntField(metricsObj, gFontMetricsInt_fieldID.top, SkScalarFloor(metrics.fTop));
+ env->SetIntField(metricsObj, gFontMetricsInt_fieldID.top, SkScalarFloorToInt(metrics.fTop));
env->SetIntField(metricsObj, gFontMetricsInt_fieldID.ascent, ascent);
env->SetIntField(metricsObj, gFontMetricsInt_fieldID.descent, descent);
- env->SetIntField(metricsObj, gFontMetricsInt_fieldID.bottom, SkScalarCeil(metrics.fBottom));
+ env->SetIntField(metricsObj, gFontMetricsInt_fieldID.bottom, SkScalarCeilToInt(metrics.fBottom));
env->SetIntField(metricsObj, gFontMetricsInt_fieldID.leading, leading);
}
return descent - ascent + leading;
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 144ac39..9279758 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -70,7 +70,7 @@
size_t totalSizeToDelete = text.getSize() + desc->getSize();
mSize -= totalSizeToDelete;
if (mDebugEnabled) {
- ALOGD("Cache value %p deleted, size = %d", desc.get(), totalSizeToDelete);
+ ALOGD("Cache value %p deleted, size = %zu", desc.get(), totalSizeToDelete);
}
}
@@ -130,7 +130,7 @@
bool removedOne = mCache.removeOldest();
LOG_ALWAYS_FATAL_IF(!removedOne, "The cache is non-empty but we "
"failed to remove the oldest entry. "
- "mSize = %u, size = %u, mMaxSize = %u, mCache.size() = %u",
+ "mSize = %u, size = %zu, mMaxSize = %u, mCache.size() = %zu",
mSize, size, mMaxSize, mCache.size());
}
}
@@ -149,7 +149,7 @@
nsecs_t totalTime = systemTime(SYSTEM_TIME_MONOTONIC) - startTime;
ALOGD("CACHE MISS: Added entry %p "
"with start = %d, count = %d, contextCount = %d, "
- "entry size %d bytes, remaining space %d bytes"
+ "entry size %zu bytes, remaining space %d bytes"
" - Compute time %0.6f ms - Put time %0.6f ms - Text = '%s'",
value.get(), start, count, contextCount, size, mMaxSize - mSize,
value->getElapsedTime() * 0.000001f,
@@ -160,7 +160,7 @@
if (mDebugEnabled) {
ALOGD("CACHE MISS: Calculated but not storing entry because it is too big "
"with start = %d, count = %d, contextCount = %d, "
- "entry size %d bytes, remaining space %d bytes"
+ "entry size %zu bytes, remaining space %d bytes"
" - Compute time %0.6f ms - Text = '%s'",
start, count, contextCount, size, mMaxSize - mSize,
value->getElapsedTime() * 0.000001f,
@@ -205,7 +205,7 @@
ALOGD("------------------------------------------------");
ALOGD("pid : %d", getpid());
ALOGD("running : %.0f seconds", timeRunningInSec);
- ALOGD("entries : %d", cacheSize);
+ ALOGD("entries : %zu", cacheSize);
ALOGD("max size : %d bytes", mMaxSize);
ALOGD("used : %d bytes according to mSize", mSize);
ALOGD("remaining : %d bytes or %2.2f percent", mMaxSize - mSize, remainingPercent);
@@ -492,7 +492,7 @@
(((ucs) & 0xfc00) == 0xdc00)
#ifndef HB_SurrogateToUcs4
-#define HB_SurrogateToUcs4_(high, low) \
+#define HB_SurrogateToUcs4(high, low) \
(((hb_codepoint_t)(high))<<10) + (low) - 0x35fdc00;
#endif
@@ -784,7 +784,7 @@
if (typeface) {
currentStyle = typeface->style();
}
- typeface = SkCreateTypefaceForScriptNG(script, currentStyle);
+ typeface = SkCreateTypefaceForScript(script, currentStyle);
#if DEBUG_GLYPHS
ALOGD("Using Harfbuzz Script %c%c%c%c, Style %d", HB_UNTAG(script), currentStyle);
#endif
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 58b61ba..307293f 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -230,7 +230,7 @@
ssize_t offset;
size_t size;
sp<IMemoryHeap> heap = dataPtr->getMemory(&offset, &size);
- ALOGV("copyAndPost: off=%ld, size=%d", offset, size);
+ ALOGV("copyAndPost: off=%zd, size=%zu", offset, size);
uint8_t *heapBase = (uint8_t*)heap->base();
if (heapBase != NULL) {
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 0132b5f..d8faaf3 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -166,7 +166,7 @@
ALOGE("Error creating AudioRecord: channel mask %#x is not valid.", channelMask);
return (jint) AUDIORECORD_ERROR_SETUP_INVALIDCHANNELMASK;
}
- uint32_t nbChannels = popcount(channelMask);
+ uint32_t channelCount = popcount(channelMask);
// compare the format against the Java constants
audio_format_t format = audioFormatToNative(audioFormat);
@@ -181,7 +181,7 @@
ALOGE("Error creating AudioRecord: frameCount is 0.");
return (jint) AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT;
}
- size_t frameSize = nbChannels * bytesPerSample;
+ size_t frameSize = channelCount * bytesPerSample;
size_t frameCount = buffSizeInBytes / frameSize;
if ((uint32_t(source) >= AUDIO_SOURCE_CNT) && (uint32_t(source) != AUDIO_SOURCE_HOTWORD)) {
@@ -220,7 +220,7 @@
lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this);
lpCallbackData->busy = false;
- lpRecorder->set((audio_source_t) source,
+ const status_t status = lpRecorder->set((audio_source_t) source,
sampleRateInHertz,
format, // word length, PCM
channelMask,
@@ -231,7 +231,6 @@
true, // threadCanCallJava
sessionId);
- const status_t status = lpRecorder->initCheck();
if (status != NO_ERROR) {
ALOGE("Error creating AudioRecord instance: initialization check failed with status %d.",
status);
@@ -312,7 +311,7 @@
if (lpRecorder == NULL) {
return;
}
- ALOGV("About to delete lpRecorder: %" PRIxPTR "\n", lpRecorder.get());
+ ALOGV("About to delete lpRecorder: %p", lpRecorder.get());
lpRecorder->stop();
audiorecord_callback_cookie *lpCookie = (audiorecord_callback_cookie *)env->GetLongField(
@@ -325,7 +324,7 @@
// delete the callback information
if (lpCookie) {
Mutex::Autolock l(sLock);
- ALOGV("deleting lpCookie: %" PRIxPTR "\n", lpCookie);
+ ALOGV("deleting lpCookie: %p", lpCookie);
while (lpCookie->busy) {
if (lpCookie->cond.waitRelative(sLock,
milliseconds(CALLBACK_COND_WAIT_TIMEOUT_MS)) !=
@@ -501,17 +500,17 @@
// returns 0 if the parameter combination is not supported.
// return -1 if there was an error querying the buffer size.
static jint android_media_AudioRecord_get_min_buff_size(JNIEnv *env, jobject thiz,
- jint sampleRateInHertz, jint nbChannels, jint audioFormat) {
+ jint sampleRateInHertz, jint channelCount, jint audioFormat) {
ALOGV(">> android_media_AudioRecord_get_min_buff_size(%d, %d, %d)",
- sampleRateInHertz, nbChannels, audioFormat);
+ sampleRateInHertz, channelCount, audioFormat);
size_t frameCount = 0;
audio_format_t format = audioFormatToNative(audioFormat);
status_t result = AudioRecord::getMinFrameCount(&frameCount,
sampleRateInHertz,
format,
- audio_channel_in_mask_from_count(nbChannels));
+ audio_channel_in_mask_from_count(channelCount));
if (result == BAD_VALUE) {
return 0;
@@ -519,7 +518,7 @@
if (result != NO_ERROR) {
return -1;
}
- return frameCount * nbChannels * audio_bytes_per_sample(format);
+ return frameCount * channelCount * audio_bytes_per_sample(format);
}
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 3a5b566..162d0c4 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -26,6 +26,7 @@
#include <utils/Log.h>
#include <media/AudioSystem.h>
#include <media/AudioTrack.h>
+#include <audio_utils/primitives.h>
#include <binder/MemoryHeapBase.h>
#include <binder/MemoryBase.h>
@@ -203,25 +204,30 @@
uint32_t afSampleRate;
size_t afFrameCount;
- if (AudioSystem::getOutputFrameCount(&afFrameCount, (audio_stream_type_t) streamType) != NO_ERROR) {
- ALOGE("Error creating AudioTrack: Could not get AudioSystem frame count.");
+ status_t status = AudioSystem::getOutputFrameCount(&afFrameCount,
+ (audio_stream_type_t) streamType);
+ if (status != NO_ERROR) {
+ ALOGE("Error %d creating AudioTrack: Could not get AudioSystem frame count "
+ "for stream type %d.", status, streamType);
return (jint) AUDIOTRACK_ERROR_SETUP_AUDIOSYSTEM;
}
- if (AudioSystem::getOutputSamplingRate(&afSampleRate, (audio_stream_type_t) streamType) != NO_ERROR) {
- ALOGE("Error creating AudioTrack: Could not get AudioSystem sampling rate.");
+ status = AudioSystem::getOutputSamplingRate(&afSampleRate, (audio_stream_type_t) streamType);
+ if (status != NO_ERROR) {
+ ALOGE("Error %d creating AudioTrack: Could not get AudioSystem sampling rate "
+ "for stream type %d.", status, streamType);
return (jint) AUDIOTRACK_ERROR_SETUP_AUDIOSYSTEM;
}
// Java channel masks don't map directly to the native definition, but it's a simple shift
// to skip the two deprecated channel configurations "default" and "mono".
- uint32_t nativeChannelMask = ((uint32_t)javaChannelMask) >> 2;
+ audio_channel_mask_t nativeChannelMask = ((uint32_t)javaChannelMask) >> 2;
if (!audio_is_output_channel(nativeChannelMask)) {
ALOGE("Error creating AudioTrack: invalid channel mask %#x.", javaChannelMask);
return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDCHANNELMASK;
}
- int nbChannels = popcount(nativeChannelMask);
+ uint32_t channelCount = popcount(nativeChannelMask);
// check the stream type
audio_stream_type_t atStreamType;
@@ -237,7 +243,7 @@
atStreamType = (audio_stream_type_t) streamType;
break;
default:
- ALOGE("Error creating AudioTrack: unknown stream type.");
+ ALOGE("Error creating AudioTrack: unknown stream type %d.", streamType);
return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDSTREAMTYPE;
}
@@ -245,8 +251,7 @@
// This function was called from Java, so we compare the format against the Java constants
audio_format_t format = audioFormatToNative(audioFormat);
if (format == AUDIO_FORMAT_INVALID) {
-
- ALOGE("Error creating AudioTrack: unsupported audio format.");
+ ALOGE("Error creating AudioTrack: unsupported audio format %d.", audioFormat);
return (jint) AUDIOTRACK_ERROR_SETUP_INVALIDFORMAT;
}
@@ -265,7 +270,7 @@
// compute the frame count
const size_t bytesPerSample = audio_bytes_per_sample(format);
- size_t frameCount = buffSizeInBytes / (nbChannels * bytesPerSample);
+ size_t frameCount = buffSizeInBytes / (channelCount * bytesPerSample);
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
@@ -303,7 +308,7 @@
switch (memoryMode) {
case MODE_STREAM:
- lpTrack->set(
+ status = lpTrack->set(
atStreamType,// stream type
sampleRateInHertz,
format,// word length, PCM
@@ -325,7 +330,7 @@
goto native_init_failure;
}
- lpTrack->set(
+ status = lpTrack->set(
atStreamType,// stream type
sampleRateInHertz,
format,// word length, PCM
@@ -344,8 +349,8 @@
goto native_init_failure;
}
- if (lpTrack->initCheck() != NO_ERROR) {
- ALOGE("Error initializing AudioTrack");
+ if (status != NO_ERROR) {
+ ALOGE("Error %d initializing AudioTrack", status);
goto native_init_failure;
}
@@ -546,10 +551,8 @@
}
int count = sizeInBytes;
int16_t *dst = (int16_t *)track->sharedBuffer()->pointer();
- const int8_t *src = (const int8_t *)(data + offsetInBytes);
- while (count--) {
- *dst++ = (int16_t)(*src++^0x80) << 8;
- }
+ const uint8_t *src = (const uint8_t *)(data + offsetInBytes);
+ memcpy_to_i16_from_u8(dst, src, count);
// even though we wrote 2*sizeInBytes, we only report sizeInBytes as written to hide
// the 8bit mixer restriction from the user of this function
written = sizeInBytes;
@@ -853,9 +856,10 @@
break;
}
- if (AudioSystem::getOutputSamplingRate(&afSamplingRate, nativeStreamType) != NO_ERROR) {
- ALOGE("AudioSystem::getOutputSamplingRate() for stream type %d failed in AudioTrack JNI",
- nativeStreamType);
+ status_t status = AudioSystem::getOutputSamplingRate(&afSamplingRate, nativeStreamType);
+ if (status != NO_ERROR) {
+ ALOGE("Error %d in AudioSystem::getOutputSamplingRate() for stream type %d "
+ "in AudioTrack JNI", status, nativeStreamType);
return DEFAULT_OUTPUT_SAMPLE_RATE;
} else {
return afSamplingRate;
@@ -867,7 +871,7 @@
// returns the minimum required size for the successful creation of a streaming AudioTrack
// returns -1 if there was an error querying the hardware.
static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env, jobject thiz,
- jint sampleRateInHertz, jint nbChannels, jint audioFormat) {
+ jint sampleRateInHertz, jint channelCount, jint audioFormat) {
size_t frameCount;
const status_t status = AudioTrack::getMinFrameCount(&frameCount, AUDIO_STREAM_DEFAULT,
@@ -879,21 +883,26 @@
}
const audio_format_t format = audioFormatToNative(audioFormat);
const size_t bytesPerSample = audio_bytes_per_sample(format);
- return frameCount * nbChannels * bytesPerSample;
+ return frameCount * channelCount * bytesPerSample;
}
// ----------------------------------------------------------------------------
-static void
+static jint
android_media_AudioTrack_setAuxEffectSendLevel(JNIEnv *env, jobject thiz, jfloat level )
{
sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
if (lpTrack == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioTrack pointer for setAuxEffectSendLevel()");
- return;
+ return -1;
}
- lpTrack->setAuxEffectSendLevel(level);
+ status_t status = lpTrack->setAuxEffectSendLevel(level);
+ if (status != NO_ERROR) {
+ ALOGE("AudioTrack::setAuxEffectSendLevel() for level %g failed with status %d",
+ level, status);
+ }
+ return (jint) status;
}
// ----------------------------------------------------------------------------
@@ -949,7 +958,7 @@
{"native_get_min_buff_size",
"(III)I", (void *)android_media_AudioTrack_get_min_buff_size},
{"native_setAuxEffectSendLevel",
- "(F)V", (void *)android_media_AudioTrack_setAuxEffectSendLevel},
+ "(F)I", (void *)android_media_AudioTrack_setAuxEffectSendLevel},
{"native_attachAuxEffect",
"(I)I", (void *)android_media_AudioTrack_attachAuxEffect},
};
diff --git a/core/jni/android_net_LocalSocketImpl.cpp b/core/jni/android_net_LocalSocketImpl.cpp
index 9f79f74..98f4bed 100644
--- a/core/jni/android_net_LocalSocketImpl.cpp
+++ b/core/jni/android_net_LocalSocketImpl.cpp
@@ -111,7 +111,7 @@
/* private native void listen_native(int fd, int backlog) throws IOException; */
static void
-socket_listen (JNIEnv *env, jobject object, jobject fileDescriptor, int backlog)
+socket_listen (JNIEnv *env, jobject object, jobject fileDescriptor, jint backlog)
{
int ret;
int fd;
@@ -231,7 +231,7 @@
}
static jint
-socket_getOption(JNIEnv *env, jobject object, jobject fileDescriptor, int optID)
+socket_getOption(JNIEnv *env, jobject object, jobject fileDescriptor, jint optID)
{
int ret, value;
int opt, level;
@@ -279,7 +279,7 @@
}
static void socket_setOption(
- JNIEnv *env, jobject object, jobject fileDescriptor, int optID,
+ JNIEnv *env, jobject object, jobject fileDescriptor, jint optID,
jint boolValue, jint intValue) {
int ret;
int optname;
diff --git a/core/jni/android_nio_utils.cpp b/core/jni/android_nio_utils.cpp
index 7cbbe12..59d6e41 100644
--- a/core/jni/android_nio_utils.cpp
+++ b/core/jni/android_nio_utils.cpp
@@ -37,7 +37,7 @@
gNioJNI.getBasePointerID, buffer);
if (pointer != 0L) {
*array = NULL;
- return (void *) (jint) pointer;
+ return reinterpret_cast<void *>(pointer);
}
*array = (jarray) _env->CallStaticObjectMethod(gNioJNI.nioAccessClass,
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index a041693..d4873d6 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -800,7 +800,7 @@
fprintf(fp, "Total memory: %zu\n", totalMemory);
fprintf(fp, "Allocation records: %zd\n", recordCount);
if (backtraceSize != BACKTRACE_SIZE) {
- fprintf(fp, "WARNING: mismatched backtrace sizes (%d vs. %d)\n",
+ fprintf(fp, "WARNING: mismatched backtrace sizes (%zu vs. %d)\n",
backtraceSize, BACKTRACE_SIZE);
}
fprintf(fp, "\n");
@@ -823,7 +823,11 @@
if (backtrace[bt] == 0) {
break;
} else {
+#ifdef __LP64__
+ fprintf(fp, " %016x", backtrace[bt]);
+#else
fprintf(fp, " %08x", backtrace[bt]);
+#endif
}
}
fprintf(fp, "\n");
diff --git a/core/jni/android_server_NetworkManagementSocketTagger.cpp b/core/jni/android_server_NetworkManagementSocketTagger.cpp
index 12beff7..7e12b1e 100644
--- a/core/jni/android_server_NetworkManagementSocketTagger.cpp
+++ b/core/jni/android_server_NetworkManagementSocketTagger.cpp
@@ -47,8 +47,8 @@
return (jint)res;
}
-static int QTagUid_untagSocketFd(JNIEnv* env, jclass,
- jobject fileDescriptor) {
+static jint QTagUid_untagSocketFd(JNIEnv* env, jclass,
+ jobject fileDescriptor) {
int userFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
if (env->ExceptionOccurred() != NULL) {
diff --git a/core/jni/android_text_AndroidBidi.cpp b/core/jni/android_text_AndroidBidi.cpp
index d50a69f..6f7ee49 100644
--- a/core/jni/android_text_AndroidBidi.cpp
+++ b/core/jni/android_text_AndroidBidi.cpp
@@ -26,7 +26,7 @@
namespace android {
static jint runBidi(JNIEnv* env, jobject obj, jint dir, jcharArray chsArray,
- jbyteArray infoArray, int n, jboolean haveInfo)
+ jbyteArray infoArray, jint n, jboolean haveInfo)
{
// Parameters are checked on java side
// Failures from GetXXXArrayElements indicate a serious out-of-memory condition
diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp
index 8b85a7b7..94bd40f 100644
--- a/core/jni/android_text_AndroidCharacter.cpp
+++ b/core/jni/android_text_AndroidCharacter.cpp
@@ -51,7 +51,8 @@
namespace android {
-static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray, jbyteArray destArray, int count)
+static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray,
+ jbyteArray destArray, jint count)
{
ScopedCharArrayRO src(env, srcArray);
if (src.get() == NULL) {
@@ -102,7 +103,7 @@
}
static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray,
- int start, int count, jbyteArray destArray)
+ jint start, jint count, jbyteArray destArray)
{
ScopedCharArrayRO src(env, srcArray);
if (src.get() == NULL) {
@@ -144,20 +145,20 @@
}
}
-static jboolean mirror(JNIEnv* env, jobject obj, jcharArray charArray, int start, int count)
+static jboolean mirror(JNIEnv* env, jobject obj, jcharArray charArray, jint start, jint count)
{
ScopedCharArrayRW data(env, charArray);
if (data.get() == NULL) {
- return false;
+ return JNI_FALSE;
}
if (start < 0 || start > start + count
|| env->GetArrayLength(charArray) < start + count) {
jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL);
- return false;
+ return JNI_FALSE;
}
- bool ret = false;
+ jboolean ret = JNI_FALSE;
for (int i = start; i < start + count; i++) {
// XXX this thinks it knows that surrogates are never mirrored
@@ -166,7 +167,7 @@
if (c1 != c2) {
data[i] = c2;
- ret = true;
+ ret = JNI_TRUE;
}
}
return ret;
diff --git a/core/jni/android_text_format_Time.cpp b/core/jni/android_text_format_Time.cpp
index aa2c5f39..28a8a5d 100644
--- a/core/jni/android_text_format_Time.cpp
+++ b/core/jni/android_text_format_Time.cpp
@@ -117,7 +117,7 @@
time2java(env, This, t);
RELEASE_TIMEZONE(This, t)
- return result;
+ return static_cast<jlong>(result);
}
static void android_text_format_Time_switchTimezone(JNIEnv* env, jobject This,
@@ -155,7 +155,7 @@
RELEASE_TIMEZONE(aObject, a)
RELEASE_TIMEZONE(bObject, b)
- return result;
+ return static_cast<jint>(result);
}
static jstring android_text_format_Time_format2445(JNIEnv* env, jobject This)
@@ -346,7 +346,7 @@
RELEASE_TIMEZONE(This, t)
- return result;
+ return static_cast<jlong>(result);
}
static void android_text_format_Time_set(JNIEnv* env, jobject This, jlong millis)
@@ -400,10 +400,10 @@
if (len < 8) {
jniThrowException(env, "android/util/TimeFormatException",
"String too short -- expected at least 8 characters.");
- return false;
+ return JNI_FALSE;
}
- jboolean inUtc = false;
+ jboolean inUtc = JNI_FALSE;
ScopedStringChars s(env, strObj);
@@ -414,49 +414,49 @@
n += get_char(env, s, 1, 100, &thrown);
n += get_char(env, s, 2, 10, &thrown);
n += get_char(env, s, 3, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_yearField, n);
// month
n = get_char(env, s, 4, 10, &thrown);
n += get_char(env, s, 5, 1, &thrown);
n--;
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_monField, n);
// day of month
n = get_char(env, s, 6, 10, &thrown);
n += get_char(env, s, 7, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_mdayField, n);
if (len > 8) {
// T
- if (!check_char(env, s, 8, 'T')) return false;
+ if (!check_char(env, s, 8, 'T')) return JNI_FALSE;
env->SetBooleanField(This, g_allDayField, JNI_FALSE);
// hour
n = get_char(env, s, 9, 10, &thrown);
n += get_char(env, s, 10, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_hourField, n);
// min
n = get_char(env, s, 11, 10, &thrown);
n += get_char(env, s, 12, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_minField, n);
// sec
n = get_char(env, s, 13, 10, &thrown);
n += get_char(env, s, 14, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_secField, n);
if (len > 15) {
// Z
- if (!check_char(env, s, 15, 'Z')) return false;
- inUtc = true;
+ if (!check_char(env, s, 15, 'Z')) return JNI_FALSE;
+ inUtc = JNI_TRUE;
}
} else {
env->SetBooleanField(This, g_allDayField, JNI_TRUE);
@@ -481,10 +481,10 @@
if (len < 10) {
jniThrowException(env, "android/util/TimeFormatException",
"String too short --- expected at least 10 characters.");
- return false;
+ return JNI_FALSE;
}
- jboolean inUtc = false;
+ jboolean inUtc = JNI_FALSE;
ScopedStringChars s(env, strObj);
@@ -495,57 +495,57 @@
n += get_char(env, s, 1, 100, &thrown);
n += get_char(env, s, 2, 10, &thrown);
n += get_char(env, s, 3, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_yearField, n);
// -
- if (!check_char(env, s, 4, '-')) return false;
+ if (!check_char(env, s, 4, '-')) return JNI_FALSE;
// month
n = get_char(env, s, 5, 10, &thrown);
n += get_char(env, s, 6, 1, &thrown);
--n;
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_monField, n);
// -
- if (!check_char(env, s, 7, '-')) return false;
+ if (!check_char(env, s, 7, '-')) return JNI_FALSE;
// day
n = get_char(env, s, 8, 10, &thrown);
n += get_char(env, s, 9, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_mdayField, n);
if (len >= 19) {
// T
- if (!check_char(env, s, 10, 'T')) return false;
+ if (!check_char(env, s, 10, 'T')) return JNI_FALSE;
env->SetBooleanField(This, g_allDayField, JNI_FALSE);
// hour
n = get_char(env, s, 11, 10, &thrown);
n += get_char(env, s, 12, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
int hour = n;
// env->SetIntField(This, g_hourField, n);
// :
- if (!check_char(env, s, 13, ':')) return false;
+ if (!check_char(env, s, 13, ':')) return JNI_FALSE;
// minute
n = get_char(env, s, 14, 10, &thrown);
n += get_char(env, s, 15, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
int minute = n;
// env->SetIntField(This, g_minField, n);
// :
- if (!check_char(env, s, 16, ':')) return false;
+ if (!check_char(env, s, 16, ':')) return JNI_FALSE;
// second
n = get_char(env, s, 17, 10, &thrown);
n += get_char(env, s, 18, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
env->SetIntField(This, g_secField, n);
// skip the '.XYZ' -- we don't care about subsecond precision.
@@ -579,32 +579,32 @@
jniThrowExceptionFmt(env, "android/util/TimeFormatException",
"Unexpected character 0x%02x at position %d. Expected + or -",
c, tz_index);
- return false;
+ return JNI_FALSE;
}
- inUtc = true;
+ inUtc = JNI_TRUE;
if (offset != 0) {
if (len < tz_index + 6) {
jniThrowExceptionFmt(env, "android/util/TimeFormatException",
"Unexpected length; should be %d characters",
tz_index + 6);
- return false;
+ return JNI_FALSE;
}
// hour
n = get_char(env, s, tz_index + 1, 10, &thrown);
n += get_char(env, s, tz_index + 2, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
n *= offset;
hour += n;
// :
- if (!check_char(env, s, tz_index + 3, ':')) return false;
+ if (!check_char(env, s, tz_index + 3, ':')) return JNI_FALSE;
// minute
n = get_char(env, s, tz_index + 4, 10, &thrown);
n += get_char(env, s, tz_index + 5, 1, &thrown);
- if (thrown) return false;
+ if (thrown) return JNI_FALSE;
n *= offset;
minute += n;
}
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 9dde701a..4147608 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -73,6 +73,13 @@
jfieldID mObject;
} gAssetManagerOffsets;
+static struct sparsearray_offsets_t
+{
+ jclass classObject;
+ jmethodID constructor;
+ jmethodID put;
+} gSparseArrayOffsets;
+
jclass g_stringClass = NULL;
// ----------------------------------------------------------------------------
@@ -905,6 +912,26 @@
return str;
}
+static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
+{
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
+ }
+
+ const ResTable& res = am->getResources();
+
+ jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
+ gSparseArrayOffsets.constructor);
+ const size_t N = res.getBasePackageCount();
+ for (size_t i = 0; i < N; i++) {
+ const String16 name = res.getBasePackageName(i);
+ env->CallVoidMethod(sparseArray, gSparseArrayOffsets.put, (jint) res.getBasePackageId(i),
+ env->NewString(name, name.size()));
+ }
+ return sparseArray;
+}
+
static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
{
AssetManager* am = assetManagerForJavaObject(env, clazz);
@@ -1675,16 +1702,19 @@
return 0;
}
- Asset* a = cookie
- ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_BUFFER)
- : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER);
+ int32_t assetCookie = static_cast<int32_t>(cookie);
+ Asset* a = assetCookie
+ ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
+ : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
if (a == NULL) {
jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
return 0;
}
- ResXMLTree* block = new ResXMLTree();
+ const DynamicRefTable* dynamicRefTable =
+ am->getResources().getDynamicRefTableForCookie(assetCookie);
+ ResXMLTree* block = new ResXMLTree(dynamicRefTable);
status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
a->close();
delete a;
@@ -1972,6 +2002,8 @@
(void*) android_content_AssetManager_getNativeStringBlock },
{ "getCookieName","(I)Ljava/lang/String;",
(void*) android_content_AssetManager_getCookieName },
+ { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
+ (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
// Themes.
{ "newTheme", "()J",
@@ -2068,6 +2100,16 @@
g_stringClass = (jclass)env->NewGlobalRef(stringClass);
LOG_FATAL_IF(g_stringClass == NULL, "Unable to create global reference for class java/lang/String");
+ jclass sparseArrayClass = env->FindClass("android/util/SparseArray");
+ LOG_FATAL_IF(sparseArrayClass == NULL, "Unable to find class android/util/SparseArray");
+ gSparseArrayOffsets.classObject = (jclass) env->NewGlobalRef(sparseArrayClass);
+ gSparseArrayOffsets.constructor =
+ env->GetMethodID(gSparseArrayOffsets.classObject, "<init>", "()V");
+ LOG_FATAL_IF(gSparseArrayOffsets.constructor == NULL, "Unable to find SparseArray.<init>()");
+ gSparseArrayOffsets.put =
+ env->GetMethodID(gSparseArrayOffsets.classObject, "put", "(ILjava/lang/Object;)V");
+ LOG_FATAL_IF(gSparseArrayOffsets.put == NULL, "Unable to find SparseArray.put(int, V)");
+
return AndroidRuntime::registerNativeMethods(env,
"android/content/res/AssetManager", gAssetManagerMethods, NELEM(gAssetManagerMethods));
}
diff --git a/core/jni/android_util_Log.cpp b/core/jni/android_util_Log.cpp
index 536a582..93dcbef 100644
--- a/core/jni/android_util_Log.cpp
+++ b/core/jni/android_util_Log.cpp
@@ -85,7 +85,7 @@
jboolean result = false;
if ((strlen(chars)+sizeof(LOG_NAMESPACE)) > PROPERTY_KEY_MAX) {
char buf2[200];
- snprintf(buf2, sizeof(buf2), "Log tag \"%s\" exceeds limit of %d characters\n",
+ snprintf(buf2, sizeof(buf2), "Log tag \"%s\" exceeds limit of %zu characters\n",
chars, PROPERTY_KEY_MAX - sizeof(LOG_NAMESPACE));
jniThrowException(env, "java/lang/IllegalArgumentException", buf2);
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index cbed99f..a4efed7 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -19,8 +19,8 @@
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
+#include <cutils/process_name.h>
#include <cutils/sched_policy.h>
#include <utils/String8.h>
#include <utils/Vector.h>
@@ -385,7 +385,9 @@
}
if (name8.size() > 0) {
- ProcessState::self()->setArgV0(name8.string());
+ const char* procName = name8.string();
+ set_process_name(procName);
+ AndroidRuntime::getRuntime()->setArgv0(procName);
}
}
diff --git a/core/jni/android_util_XmlBlock.cpp b/core/jni/android_util_XmlBlock.cpp
index 03de5c0..2cccb83 100644
--- a/core/jni/android_util_XmlBlock.cpp
+++ b/core/jni/android_util_XmlBlock.cpp
@@ -47,10 +47,11 @@
}
jbyte* b = env->GetByteArrayElements(bArray, NULL);
- ResXMLTree* osb = new ResXMLTree(b+off, len, true);
+ ResXMLTree* osb = new ResXMLTree();
+ osb->setTo(b+off, len, true);
env->ReleaseByteArrayElements(bArray, b, 0);
- if (osb == NULL || osb->getError() != NO_ERROR) {
+ if (osb->getError() != NO_ERROR) {
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
return 0;
}
@@ -113,6 +114,8 @@
return 1;
case ResXMLParser::BAD_DOCUMENT:
goto bad;
+ default:
+ break;
}
} while (true);
diff --git a/core/jni/android_view_GLRenderer.cpp b/core/jni/android_view_GLRenderer.cpp
index e45c1b9..180c625 100644
--- a/core/jni/android_view_GLRenderer.cpp
+++ b/core/jni/android_view_GLRenderer.cpp
@@ -26,6 +26,8 @@
#include <utils/Timers.h>
+#include <private/hwui/DrawGlInfo.h>
+
#include <Caches.h>
#include <Extensions.h>
#include <LayerRenderer.h>
@@ -155,6 +157,14 @@
renderNode->updateProperties();
}
+static void android_view_GLRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
+ jlong functorPtr, jboolean hasContext) {
+ using namespace android::uirenderer;
+ Functor* functor = reinterpret_cast<Functor*>(functorPtr);
+ DrawGlInfo::Mode mode = hasContext ? DrawGlInfo::kModeProcess : DrawGlInfo::kModeProcessNoContext;
+ (*functor)(mode, NULL);
+}
+
#endif // USE_OPENGL_RENDERER
// ----------------------------------------------------------------------------
@@ -187,6 +197,7 @@
{ "nDestroyLayer", "(J)V", (void*) android_view_GLRenderer_destroyLayer },
{ "nSetDisplayListData", "(JJ)V", (void*) android_view_GLRenderer_setDisplayListData },
{ "nUpdateRenderNodeProperties", "(J)V", (void*) android_view_GLRenderer_updateRenderNodeProperties },
+ { "nInvokeFunctor", "(JZ)V", (void*) android_view_GLRenderer_invokeFunctor },
#endif
{ "setupShadersDiskCache", "(Ljava/lang/String;)V",
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 5c7e773..d079349c 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -69,7 +69,7 @@
}
// ----------------------------------------------------------------------------
-// RenderProperties
+// RenderProperties - setters
// ----------------------------------------------------------------------------
static void android_view_RenderNode_setCaching(JNIEnv* env,
@@ -115,23 +115,38 @@
jint right, jint bottom, jfloat radius) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom, radius);
+ displayList->mutateStagingProperties().updateClipPath();
}
+
static void android_view_RenderNode_setOutlineConvexPath(JNIEnv* env,
jobject clazz, jlong displayListPtr, jlong outlinePathPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
SkPath* outlinePath = reinterpret_cast<SkPath*>(outlinePathPtr);
displayList->mutateStagingProperties().mutableOutline().setConvexPath(outlinePath);
+ displayList->mutateStagingProperties().updateClipPath();
}
+
static void android_view_RenderNode_setOutlineEmpty(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->mutateStagingProperties().mutableOutline().setEmpty();
+ displayList->mutateStagingProperties().updateClipPath();
}
static void android_view_RenderNode_setClipToOutline(JNIEnv* env,
jobject clazz, jlong displayListPtr, jboolean clipToOutline) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
displayList->mutateStagingProperties().mutableOutline().setShouldClip(clipToOutline);
+ displayList->mutateStagingProperties().updateClipPath();
+}
+
+static void android_view_RenderNode_setRevealClip(JNIEnv* env,
+ jobject clazz, jlong displayListPtr, jboolean shouldClip, jboolean inverseClip,
+ jfloat x, jfloat y, jfloat radius) {
+ RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+ displayList->mutateStagingProperties().mutableRevealClip().set(
+ shouldClip, inverseClip, x, y, radius);
+ displayList->mutateStagingProperties().updateClipPath();
}
static void android_view_RenderNode_setAlpha(JNIEnv* env,
@@ -194,22 +209,6 @@
displayList->mutateStagingProperties().setScaleY(sy);
}
-static void android_view_RenderNode_setTransformationInfo(JNIEnv* env,
- jobject clazz, jlong displayListPtr, float alpha,
- float translationX, float translationY, float translationZ,
- float rotation, float rotationX, float rotationY, float scaleX, float scaleY) {
- RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
- displayList->mutateStagingProperties().setAlpha(alpha);
- displayList->mutateStagingProperties().setTranslationX(translationX);
- displayList->mutateStagingProperties().setTranslationY(translationY);
- displayList->mutateStagingProperties().setTranslationZ(translationZ);
- displayList->mutateStagingProperties().setRotation(rotation);
- displayList->mutateStagingProperties().setRotationX(rotationX);
- displayList->mutateStagingProperties().setRotationY(rotationY);
- displayList->mutateStagingProperties().setScaleX(scaleX);
- displayList->mutateStagingProperties().setScaleY(scaleY);
-}
-
static void android_view_RenderNode_setPivotX(JNIEnv* env,
jobject clazz, jlong displayListPtr, float px) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
@@ -271,6 +270,10 @@
displayList->mutateStagingProperties().offsetTopBottom(offset);
}
+// ----------------------------------------------------------------------------
+// RenderProperties - getters
+// ----------------------------------------------------------------------------
+
static jboolean android_view_RenderNode_hasOverlappingRendering(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
@@ -337,6 +340,12 @@
return displayList->stagingProperties().getTranslationY();
}
+static jfloat android_view_RenderNode_getTranslationZ(JNIEnv* env,
+ jobject clazz, jlong displayListPtr) {
+ RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+ return displayList->stagingProperties().getTranslationZ();
+}
+
static jfloat android_view_RenderNode_getRotation(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
@@ -355,6 +364,53 @@
return displayList->stagingProperties().getRotationY();
}
+static jboolean android_view_RenderNode_isPivotExplicitlySet(JNIEnv* env,
+ jobject clazz, jlong displayListPtr) {
+ RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+ return displayList->stagingProperties().isPivotExplicitlySet();
+}
+
+static jboolean android_view_RenderNode_hasIdentityMatrix(JNIEnv* env,
+ jobject clazz, jlong displayListPtr) {
+ RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+ return displayList->stagingProperties().getMatrixFlags() == 0;
+}
+
+// ----------------------------------------------------------------------------
+// RenderProperties - computed getters
+// ----------------------------------------------------------------------------
+
+static void android_view_RenderNode_getTransformMatrix(JNIEnv* env,
+ jobject clazz, jlong displayListPtr, jlong outMatrixPtr) {
+ RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+ SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
+
+ displayList->mutateStagingProperties().updateMatrix();
+ const SkMatrix* transformMatrix = displayList->stagingProperties().getTransformMatrix();
+
+ if (displayList->stagingProperties().getMatrixFlags() == TRANSLATION) {
+ outMatrix->setTranslate(displayList->stagingProperties().getTranslationX(),
+ displayList->stagingProperties().getTranslationY());
+ } else if (transformMatrix) {
+ *outMatrix = *transformMatrix;
+ } else {
+ outMatrix->setIdentity();
+ }
+}
+
+static void android_view_RenderNode_getInverseTransformMatrix(JNIEnv* env,
+ jobject clazz, jlong displayListPtr, jlong outMatrixPtr) {
+ // load transform matrix
+ android_view_RenderNode_getTransformMatrix(env, clazz, displayListPtr, outMatrixPtr);
+ SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
+
+ // return it inverted
+ if (!outMatrix->invert(outMatrix)) {
+ // failed to load inverse, pass back identity
+ outMatrix->setIdentity();
+ }
+}
+
static jfloat android_view_RenderNode_getPivotX(JNIEnv* env,
jobject clazz, jlong displayListPtr) {
RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
@@ -396,6 +452,7 @@
{ "nSetOutlineConvexPath", "(JJ)V", (void*) android_view_RenderNode_setOutlineConvexPath },
{ "nSetOutlineEmpty", "(J)V", (void*) android_view_RenderNode_setOutlineEmpty },
{ "nSetClipToOutline", "(JZ)V", (void*) android_view_RenderNode_setClipToOutline },
+ { "nSetRevealClip", "(JZZFFF)V", (void*) android_view_RenderNode_setRevealClip },
{ "nSetAlpha", "(JF)V", (void*) android_view_RenderNode_setAlpha },
{ "nSetHasOverlappingRendering", "(JZ)V",
@@ -408,8 +465,6 @@
{ "nSetRotationY", "(JF)V", (void*) android_view_RenderNode_setRotationY },
{ "nSetScaleX", "(JF)V", (void*) android_view_RenderNode_setScaleX },
{ "nSetScaleY", "(JF)V", (void*) android_view_RenderNode_setScaleY },
- { "nSetTransformationInfo","(JFFFFFFFFF)V",
- (void*) android_view_RenderNode_setTransformationInfo },
{ "nSetPivotX", "(JF)V", (void*) android_view_RenderNode_setPivotX },
{ "nSetPivotY", "(JF)V", (void*) android_view_RenderNode_setPivotY },
{ "nSetCameraDistance", "(JF)V", (void*) android_view_RenderNode_setCameraDistance },
@@ -432,11 +487,18 @@
{ "nGetScaleY", "(J)F", (void*) android_view_RenderNode_getScaleY },
{ "nGetTranslationX", "(J)F", (void*) android_view_RenderNode_getTranslationX },
{ "nGetTranslationY", "(J)F", (void*) android_view_RenderNode_getTranslationY },
+ { "nGetTranslationZ", "(J)F", (void*) android_view_RenderNode_getTranslationZ },
{ "nGetRotation", "(J)F", (void*) android_view_RenderNode_getRotation },
{ "nGetRotationX", "(J)F", (void*) android_view_RenderNode_getRotationX },
{ "nGetRotationY", "(J)F", (void*) android_view_RenderNode_getRotationY },
- { "nGetPivotX", "(J)F", (void*) android_view_RenderNode_getPivotX },
- { "nGetPivotY", "(J)F", (void*) android_view_RenderNode_getPivotY },
+ { "nIsPivotExplicitlySet", "(J)Z", (void*) android_view_RenderNode_isPivotExplicitlySet },
+ { "nHasIdentityMatrix", "(J)Z", (void*) android_view_RenderNode_hasIdentityMatrix },
+
+ { "nGetTransformMatrix", "(JJ)V", (void*) android_view_RenderNode_getTransformMatrix },
+ { "nGetInverseTransformMatrix","(JJ)V", (void*) android_view_RenderNode_getInverseTransformMatrix },
+
+ { "nGetPivotX", "(J)F", (void*) android_view_RenderNode_getPivotX },
+ { "nGetPivotY", "(J)F", (void*) android_view_RenderNode_getPivotY },
#endif
};
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index c5ab284..159ffb2 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -58,36 +58,11 @@
jfieldID secure;
} gPhysicalDisplayInfoClassInfo;
-
-class ScreenshotPixelRef : public SkPixelRef {
-public:
- ScreenshotPixelRef(const SkImageInfo& info, ScreenshotClient* screenshot) :
- SkPixelRef(info),
- mScreenshot(screenshot) {
- setImmutable();
- }
-
- virtual ~ScreenshotPixelRef() {
- delete mScreenshot;
- }
-
-protected:
- // overrides from SkPixelRef
- virtual void* onLockPixels(SkColorTable** ct) {
- *ct = NULL;
- return (void*)mScreenshot->getPixels();
- }
-
- virtual void onUnlockPixels() {
- }
-
- SK_DECLARE_UNFLATTENABLE_OBJECT()
-private:
- ScreenshotClient* mScreenshot;
-
- typedef SkPixelRef INHERITED;
-};
-
+// Implements SkMallocPixelRef::ReleaseProc, to delete the screenshot on unref.
+void DeleteScreenshot(void* addr, void* context) {
+ SkASSERT(addr == ((ScreenshotClient*) context)->getPixels());
+ delete ((ScreenshotClient*) context);
+}
// ----------------------------------------------------------------------------
@@ -167,20 +142,19 @@
}
}
- // takes ownership of ScreenshotClient
- ScreenshotPixelRef* pixels = new ScreenshotPixelRef(screenshotInfo, screenshot);
const ssize_t rowBytes =
screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());
SkBitmap* bitmap = new SkBitmap();
bitmap->setConfig(screenshotInfo, (size_t)rowBytes);
if (screenshotInfo.fWidth > 0 && screenshotInfo.fHeight > 0) {
+ // takes ownership of ScreenshotClient
+ SkMallocPixelRef* pixels = SkMallocPixelRef::NewWithProc(screenshotInfo,
+ (size_t) rowBytes, NULL, (void*) screenshot->getPixels(), &DeleteScreenshot,
+ (void*) screenshot);
+ pixels->setImmutable();
bitmap->setPixelRef(pixels)->unref();
bitmap->lockPixels();
- } else {
- // be safe with an empty bitmap.
- delete pixels;
- bitmap->setPixels(NULL);
}
return GraphicsJNI::createBitmap(env, bitmap,
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 28cee4b..98bec1b 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -139,6 +139,13 @@
proxy->detachFunctor(functor);
}
+static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
+ jlong proxyPtr, jlong functorPtr, jboolean waitForCompletion) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ Functor* functor = reinterpret_cast<Functor*>(functorPtr);
+ proxy->invokeFunctor(functor, waitForCompletion);
+}
+
static void android_view_ThreadedRenderer_runWithGlContext(JNIEnv* env, jobject clazz,
jlong proxyPtr, jobject jrunnable) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -196,6 +203,7 @@
{ "nDestroyCanvas", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvas },
{ "nAttachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_attachFunctor },
{ "nDetachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_detachFunctor },
+ { "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
{ "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
{ "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
{ "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
new file mode 100644
index 0000000..a61fa87
--- /dev/null
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -0,0 +1,608 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include "android_runtime/AndroidRuntime.h"
+
+// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
+#include <sys/mount.h>
+#include <linux/fs.h>
+
+#include <grp.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "cutils/fs.h"
+#include "cutils/multiuser.h"
+#include "cutils/sched_policy.h"
+#include "utils/String8.h"
+#include "JNIHelp.h"
+#include "ScopedLocalRef.h"
+#include "ScopedPrimitiveArray.h"
+#include "ScopedUtfChars.h"
+
+#if defined(HAVE_PRCTL)
+#include <sys/prctl.h>
+#endif
+
+#include <selinux/android.h>
+
+#if defined(__linux__)
+#include <sys/personality.h>
+#include <sys/utsname.h>
+#if defined(HAVE_ANDROID_OS)
+#include <sys/capability.h>
+#endif
+#endif
+
+namespace {
+
+using android::String8;
+
+static pid_t gSystemServerPid = 0;
+
+static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
+static jclass gZygoteClass;
+static jmethodID gCallPostForkChildHooks;
+
+// Must match values in com.android.internal.os.Zygote.
+enum MountExternalKind {
+ MOUNT_EXTERNAL_NONE = 0,
+ MOUNT_EXTERNAL_SINGLEUSER = 1,
+ MOUNT_EXTERNAL_MULTIUSER = 2,
+ MOUNT_EXTERNAL_MULTIUSER_ALL = 3,
+};
+
+static void RuntimeAbort(JNIEnv* env) {
+ env->FatalError("RuntimeAbort");
+}
+
+// This signal handler is for zygote mode, since the zygote must reap its children
+static void SigChldHandler(int /*signal_number*/) {
+ pid_t pid;
+ int status;
+
+ while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
+ // Log process-death status that we care about. In general it is
+ // not safe to call LOG(...) from a signal handler because of
+ // possible reentrancy. However, we know a priori that the
+ // current implementation of LOG() is safe to call from a SIGCHLD
+ // handler in the zygote process. If the LOG() implementation
+ // changes its locking strategy or its use of syscalls within the
+ // lazy-init critical section, its use here may become unsafe.
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status)) {
+ ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
+ } else if (false) {
+ ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
+ }
+ } else if (WIFSIGNALED(status)) {
+ if (WTERMSIG(status) != SIGKILL) {
+ ALOGI("Process %d exited cleanly (%d)", pid, WTERMSIG(status));
+ } else if (false) {
+ ALOGI("Process %d exited cleanly (%d)", pid, WTERMSIG(status));
+ }
+#ifdef WCOREDUMP
+ if (WCOREDUMP(status)) {
+ ALOGI("Process %d dumped core.", pid);
+ }
+#endif /* ifdef WCOREDUMP */
+ }
+
+ // If the just-crashed process is the system_server, bring down zygote
+ // so that it is restarted by init and system server will be restarted
+ // from there.
+ if (pid == gSystemServerPid) {
+ ALOGE("Exit zygote because system server (%d) has terminated");
+ kill(getpid(), SIGKILL);
+ }
+ }
+
+ if (pid < 0) {
+ ALOGW("Zygote SIGCHLD error in waitpid: %d", errno);
+ }
+}
+
+// Configures the SIGCHLD handler for the zygote process. This is configured
+// very late, because earlier in the runtime we may fork() and exec()
+// other processes, and we want to waitpid() for those rather than
+// have them be harvested immediately.
+//
+// This ends up being called repeatedly before each fork(), but there's
+// no real harm in that.
+static void SetSigChldHandler() {
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = SigChldHandler;
+
+ int err = sigaction(SIGCHLD, &sa, NULL);
+ if (err < 0) {
+ ALOGW("Error setting SIGCHLD handler: %d", errno);
+ }
+}
+
+// Sets the SIGCHLD handler back to default behavior in zygote children.
+static void UnsetSigChldHandler() {
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = SIG_DFL;
+
+ int err = sigaction(SIGCHLD, &sa, NULL);
+ if (err < 0) {
+ ALOGW("Error unsetting SIGCHLD handler: %d", errno);
+ }
+}
+
+// Calls POSIX setgroups() using the int[] object as an argument.
+// A NULL argument is tolerated.
+static void SetGids(JNIEnv* env, jintArray javaGids) {
+ if (javaGids == NULL) {
+ return;
+ }
+
+ ScopedIntArrayRO gids(env, javaGids);
+ if (gids.get() == NULL) {
+ RuntimeAbort(env);
+ }
+ int rc = setgroups(gids.size(), reinterpret_cast<const gid_t*>(&gids[0]));
+ if (rc == -1) {
+ ALOGE("setgroups failed");
+ RuntimeAbort(env);
+ }
+}
+
+// Sets the resource limits via setrlimit(2) for the values in the
+// two-dimensional array of integers that's passed in. The second dimension
+// contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is
+// treated as an empty array.
+static void SetRLimits(JNIEnv* env, jobjectArray javaRlimits) {
+ if (javaRlimits == NULL) {
+ return;
+ }
+
+ rlimit rlim;
+ memset(&rlim, 0, sizeof(rlim));
+
+ for (int i = 0; i < env->GetArrayLength(javaRlimits); ++i) {
+ ScopedLocalRef<jobject> javaRlimitObject(env, env->GetObjectArrayElement(javaRlimits, i));
+ ScopedIntArrayRO javaRlimit(env, reinterpret_cast<jintArray>(javaRlimitObject.get()));
+ if (javaRlimit.size() != 3) {
+ ALOGE("rlimits array must have a second dimension of size 3");
+ RuntimeAbort(env);
+ }
+
+ rlim.rlim_cur = javaRlimit[1];
+ rlim.rlim_max = javaRlimit[2];
+
+ int rc = setrlimit(javaRlimit[0], &rlim);
+ if (rc == -1) {
+ ALOGE("setrlimit(%d, {%d, %d}) failed", javaRlimit[0], rlim.rlim_cur, rlim.rlim_max);
+ RuntimeAbort(env);
+ }
+ }
+}
+
+#if defined(HAVE_ANDROID_OS)
+
+// The debug malloc library needs to know whether it's the zygote or a child.
+extern "C" int gMallocLeakZygoteChild;
+
+static void EnableKeepCapabilities(JNIEnv* env) {
+ int rc = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+ if (rc == -1) {
+ ALOGE("prctl(PR_SET_KEEPCAPS) failed");
+ RuntimeAbort(env);
+ }
+}
+
+static void DropCapabilitiesBoundingSet(JNIEnv* env) {
+ for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
+ int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
+ if (rc == -1) {
+ if (errno == EINVAL) {
+ ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify "
+ "your kernel is compiled with file capabilities support");
+ } else {
+ ALOGE("prctl(PR_CAPBSET_DROP) failed");
+ RuntimeAbort(env);
+ }
+ }
+ }
+}
+
+static void SetCapabilities(JNIEnv* env, int64_t permitted, int64_t effective) {
+ __user_cap_header_struct capheader;
+ memset(&capheader, 0, sizeof(capheader));
+ capheader.version = _LINUX_CAPABILITY_VERSION_3;
+ capheader.pid = 0;
+
+ __user_cap_data_struct capdata[2];
+ memset(&capdata, 0, sizeof(capdata));
+ capdata[0].effective = effective;
+ capdata[1].effective = effective >> 32;
+ capdata[0].permitted = permitted;
+ capdata[1].permitted = permitted >> 32;
+
+ if (capset(&capheader, &capdata[0]) == -1) {
+ ALOGE("capset(%lld, %lld) failed", permitted, effective);
+ RuntimeAbort(env);
+ }
+}
+
+static void SetSchedulerPolicy(JNIEnv* env) {
+ errno = -set_sched_policy(0, SP_DEFAULT);
+ if (errno != 0) {
+ ALOGE("set_sched_policy(0, SP_DEFAULT) failed");
+ RuntimeAbort(env);
+ }
+}
+
+#else
+
+static int gMallocLeakZygoteChild = 0;
+
+static void EnableKeepCapabilities(JNIEnv*) {}
+static void DropCapabilitiesBoundingSet(JNIEnv*) {}
+static void SetCapabilities(JNIEnv*, int64_t, int64_t) {}
+static void SetSchedulerPolicy(JNIEnv*) {}
+
+#endif
+
+// Create a private mount namespace and bind mount appropriate emulated
+// storage for the given user.
+static bool MountEmulatedStorage(uid_t uid, jint mount_mode) {
+ if (mount_mode == MOUNT_EXTERNAL_NONE) {
+ return true;
+ }
+
+ // See storage config details at http://source.android.com/tech/storage/
+ userid_t user_id = multiuser_get_user_id(uid);
+
+ // Create a second private mount namespace for our process
+ if (unshare(CLONE_NEWNS) == -1) {
+ ALOGW("Failed to unshare(): %d", errno);
+ return false;
+ }
+
+ // Create bind mounts to expose external storage
+ if (mount_mode == MOUNT_EXTERNAL_MULTIUSER || mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
+ // These paths must already be created by init.rc
+ const char* source = getenv("EMULATED_STORAGE_SOURCE");
+ const char* target = getenv("EMULATED_STORAGE_TARGET");
+ const char* legacy = getenv("EXTERNAL_STORAGE");
+ if (source == NULL || target == NULL || legacy == NULL) {
+ ALOGW("Storage environment undefined; unable to provide external storage");
+ return false;
+ }
+
+ // Prepare source paths
+
+ // /mnt/shell/emulated/0
+ const String8 source_user(String8::format("%s/%d", source, user_id));
+ // /storage/emulated/0
+ const String8 target_user(String8::format("%s/%d", target, user_id));
+
+ if (fs_prepare_dir(source_user.string(), 0000, 0, 0) == -1
+ || fs_prepare_dir(target_user.string(), 0000, 0, 0) == -1) {
+ return false;
+ }
+
+ if (mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) {
+ // Mount entire external storage tree for all users
+ if (TEMP_FAILURE_RETRY(mount(source, target, NULL, MS_BIND, NULL)) == -1) {
+ ALOGW("Failed to mount %s to %s :%d", source, target, errno);
+ return false;
+ }
+ } else {
+ // Only mount user-specific external storage
+ if (TEMP_FAILURE_RETRY(
+ mount(source_user.string(), target_user.string(), NULL, MS_BIND, NULL)) == -1) {
+ ALOGW("Failed to mount %s to %s: %d", source_user.string(), target_user.string(), errno);
+ return false;
+ }
+ }
+
+ if (fs_prepare_dir(legacy, 0000, 0, 0) == -1) {
+ return false;
+ }
+
+ // Finally, mount user-specific path into place for legacy users
+ if (TEMP_FAILURE_RETRY(
+ mount(target_user.string(), legacy, NULL, MS_BIND | MS_REC, NULL)) == -1) {
+ ALOGW("Failed to mount %s to %s: %d", target_user.string(), legacy, errno);
+ return false;
+ }
+ } else {
+ ALOGW("Mount mode %d unsupported", mount_mode);
+ return false;
+ }
+
+ return true;
+}
+
+#if defined(__linux__)
+static bool NeedsNoRandomizeWorkaround() {
+#if !defined(__arm__)
+ return false;
+#else
+ int major;
+ int minor;
+ struct utsname uts;
+ if (uname(&uts) == -1) {
+ return false;
+ }
+
+ if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
+ return false;
+ }
+
+ // Kernels before 3.4.* need the workaround.
+ return (major < 3) || ((major == 3) && (minor < 4));
+#endif
+}
+#endif
+
+// Utility to close down the Zygote socket file descriptors while
+// the child is still running as root with Zygote's privileges. Each
+// descriptor (if any) is closed via dup2(), replacing it with a valid
+// (open) descriptor to /dev/null.
+
+static void DetachDescriptors(JNIEnv* env, jintArray fdsToClose) {
+ if (!fdsToClose) {
+ return;
+ }
+ jsize count = env->GetArrayLength(fdsToClose);
+ jint *ar = env->GetIntArrayElements(fdsToClose, 0);
+ if (!ar) {
+ ALOGE("Bad fd array");
+ RuntimeAbort(env);
+ }
+ jsize i;
+ int devnull;
+ for (i = 0; i < count; i++) {
+ devnull = open("/dev/null", O_RDWR);
+ if (devnull < 0) {
+ ALOGE("Failed to open /dev/null");
+ RuntimeAbort(env);
+ continue;
+ }
+ ALOGV("Switching descriptor %d to /dev/null: %d", ar[i], errno);
+ if (dup2(devnull, ar[i]) < 0) {
+ ALOGE("Failed dup2() on descriptor %d", ar[i]);
+ RuntimeAbort(env);
+ }
+ close(devnull);
+ }
+}
+
+void SetThreadName(const char* thread_name) {
+ bool hasAt = false;
+ bool hasDot = false;
+ const char* s = thread_name;
+ while (*s) {
+ if (*s == '.') {
+ hasDot = true;
+ } else if (*s == '@') {
+ hasAt = true;
+ }
+ s++;
+ }
+ const int len = s - thread_name;
+ if (len < 15 || hasAt || !hasDot) {
+ s = thread_name;
+ } else {
+ s = thread_name + len - 15;
+ }
+ // pthread_setname_np fails rather than truncating long strings.
+ char buf[16]; // MAX_TASK_COMM_LEN=16 is hard-coded into bionic
+ strlcpy(buf, s, sizeof(buf)-1);
+ errno = pthread_setname_np(pthread_self(), buf);
+ if (errno != 0) {
+ ALOGW("Unable to set the name of current thread to '%s'", buf);
+ }
+}
+
+// Utility routine to fork zygote and specialize the child process.
+static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
+ jint debug_flags, jobjectArray javaRlimits,
+ jlong permittedCapabilities, jlong effectiveCapabilities,
+ jint mount_external,
+ jstring java_se_info, jstring java_se_name,
+ bool is_system_server, jintArray fdsToClose) {
+ SetSigChldHandler();
+
+ pid_t pid = fork();
+
+ if (pid == 0) {
+ // The child process.
+ gMallocLeakZygoteChild = 1;
+
+ // Clean up any descriptors which must be closed immediately
+ DetachDescriptors(env, fdsToClose);
+
+ // Keep capabilities across UID change, unless we're staying root.
+ if (uid != 0) {
+ EnableKeepCapabilities(env);
+ }
+
+ DropCapabilitiesBoundingSet(env);
+
+ if (!MountEmulatedStorage(uid, mount_external)) {
+ ALOGW("Failed to mount emulated storage: %d", errno);
+ if (errno == ENOTCONN || errno == EROFS) {
+ // When device is actively encrypting, we get ENOTCONN here
+ // since FUSE was mounted before the framework restarted.
+ // When encrypted device is booting, we get EROFS since
+ // FUSE hasn't been created yet by init.
+ // In either case, continue without external storage.
+ } else {
+ ALOGE("Cannot continue without emulated storage");
+ RuntimeAbort(env);
+ }
+ }
+
+ SetGids(env, javaGids);
+
+ SetRLimits(env, javaRlimits);
+
+ int rc = setresgid(gid, gid, gid);
+ if (rc == -1) {
+ ALOGE("setresgid(%d) failed", gid);
+ RuntimeAbort(env);
+ }
+
+ rc = setresuid(uid, uid, uid);
+ if (rc == -1) {
+ ALOGE("setresuid(%d) failed", uid);
+ RuntimeAbort(env);
+ }
+
+#if defined(__linux__)
+ if (NeedsNoRandomizeWorkaround()) {
+ // Work around ARM kernel ASLR lossage (http://b/5817320).
+ int old_personality = personality(0xffffffff);
+ int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
+ if (new_personality == -1) {
+ ALOGW("personality(%d) failed", new_personality);
+ }
+ }
+#endif
+
+ SetCapabilities(env, permittedCapabilities, effectiveCapabilities);
+
+ SetSchedulerPolicy(env);
+
+#if defined(HAVE_ANDROID_OS)
+ { // NOLINT(whitespace/braces)
+ const char* se_info_c_str = NULL;
+ ScopedUtfChars* se_info = NULL;
+ if (java_se_info != NULL) {
+ se_info = new ScopedUtfChars(env, java_se_info);
+ se_info_c_str = se_info->c_str();
+ if (se_info_c_str == NULL) {
+ ALOGE("se_info_c_str == NULL");
+ RuntimeAbort(env);
+ }
+ }
+ const char* se_name_c_str = NULL;
+ ScopedUtfChars* se_name = NULL;
+ if (java_se_name != NULL) {
+ se_name = new ScopedUtfChars(env, java_se_name);
+ se_name_c_str = se_name->c_str();
+ if (se_name_c_str == NULL) {
+ ALOGE("se_name_c_str == NULL");
+ RuntimeAbort(env);
+ }
+ }
+ rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
+ if (rc == -1) {
+ ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
+ is_system_server, se_info_c_str, se_name_c_str);
+ RuntimeAbort(env);
+ }
+
+ // Make it easier to debug audit logs by setting the main thread's name to the
+ // nice name rather than "app_process".
+ if (se_info_c_str == NULL && is_system_server) {
+ se_name_c_str = "system_server";
+ }
+ if (se_info_c_str != NULL) {
+ SetThreadName(se_name_c_str);
+ }
+
+ delete se_info;
+ delete se_name;
+ }
+#else
+ UNUSED(is_system_server);
+ UNUSED(java_se_info);
+ UNUSED(java_se_name);
+#endif
+
+ UnsetSigChldHandler();
+
+ env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags);
+ if (env->ExceptionCheck()) {
+ ALOGE("Error calling post fork hooks.");
+ RuntimeAbort(env);
+ }
+ } else if (pid > 0) {
+ // the parent process
+ }
+ return pid;
+}
+} // anonymous namespace
+
+namespace android {
+
+static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
+ JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
+ jint debug_flags, jobjectArray rlimits,
+ jint mount_external, jstring se_info, jstring se_name,
+ jintArray fdsToClose) {
+ return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
+ rlimits, 0, 0, mount_external, se_info, se_name, false, fdsToClose);
+}
+
+static jint com_android_internal_os_Zygote_nativeForkSystemServer(
+ JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
+ jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
+ jlong effectiveCapabilities) {
+ pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
+ debug_flags, rlimits,
+ permittedCapabilities, effectiveCapabilities,
+ MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL);
+ if (pid > 0) {
+ // The zygote process checks whether the child process has died or not.
+ ALOGI("System server process %d has been created", pid);
+ gSystemServerPid = pid;
+ // There is a slight window that the system server process has crashed
+ // but it went unnoticed because we haven't published its pid yet. So
+ // we recheck here just to make sure that all is well.
+ int status;
+ if (waitpid(pid, &status, WNOHANG) == pid) {
+ ALOGE("System server process %d has died. Restarting Zygote!", pid);
+ RuntimeAbort(env);
+ }
+ }
+ return pid;
+}
+
+static JNINativeMethod gMethods[] = {
+ { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;[I)I",
+ (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
+ { "nativeForkSystemServer", "(II[II[[IJJ)I",
+ (void *) com_android_internal_os_Zygote_nativeForkSystemServer }
+};
+
+int register_com_android_internal_os_Zygote(JNIEnv* env) {
+ gZygoteClass = (jclass) env->NewGlobalRef(env->FindClass(kZygoteClassName));
+ if (gZygoteClass == NULL) {
+ RuntimeAbort(env);
+ }
+ gCallPostForkChildHooks = env->GetStaticMethodID(gZygoteClass, "callPostForkChildHooks", "(I)V");
+
+ return AndroidRuntime::registerNativeMethods(env, "com/android/internal/os/Zygote",
+ gMethods, NELEM(gMethods));
+}
+} // namespace android
+
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2168bd1..2a4d872 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2547,6 +2547,21 @@
android:label="@string/permlab_control_keyguard"
android:description="@string/permdesc_control_keyguard" />
+ <!-- Allows an application to listen to trust changes. Only allowed for system processes.
+ @hide -->
+ <permission android:name="android.permission.TRUST_LISTENER"
+ android:protectionLevel="signature"
+ android:label="@string/permlab_trust_listener"
+ android:description="@string/permdesc_trust_listener" />
+
+ <!-- Must be required by an {@link
+ android.service.trust.TrustAgentService},
+ to ensure that only the system can bind to it. -->
+ <permission android:name="android.permission.BIND_TRUST_AGENT_SERVICE"
+ android:protectionLevel="signature"
+ android:label="@string/permlab_bind_trust_agent_service"
+ android:description="@string/permdesc_bind_trust_agent_service" />
+
<!-- Must be required by an {@link
android.service.notification.NotificationListenerService},
to ensure that only the system can bind to it. -->
diff --git a/core/res/res/drawable/background_cache_hint_selector_holo_dark.xml b/core/res/res/color/background_cache_hint_selector_holo_dark.xml
similarity index 100%
rename from core/res/res/drawable/background_cache_hint_selector_holo_dark.xml
rename to core/res/res/color/background_cache_hint_selector_holo_dark.xml
diff --git a/core/res/res/drawable/background_cache_hint_selector_holo_light.xml b/core/res/res/color/background_cache_hint_selector_holo_light.xml
similarity index 100%
rename from core/res/res/drawable/background_cache_hint_selector_holo_light.xml
rename to core/res/res/color/background_cache_hint_selector_holo_light.xml
diff --git a/core/res/res/drawable/background_cache_hint_selector_quantum_dark.xml b/core/res/res/color/background_cache_hint_selector_quantum_dark.xml
similarity index 100%
rename from core/res/res/drawable/background_cache_hint_selector_quantum_dark.xml
rename to core/res/res/color/background_cache_hint_selector_quantum_dark.xml
diff --git a/core/res/res/drawable/background_cache_hint_selector_quantum_light.xml b/core/res/res/color/background_cache_hint_selector_quantum_light.xml
similarity index 100%
rename from core/res/res/drawable/background_cache_hint_selector_quantum_light.xml
rename to core/res/res/color/background_cache_hint_selector_quantum_light.xml
diff --git a/core/res/res/drawable-hdpi/ab_bottom_solid_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_bottom_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..406bf58
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_bottom_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_bottom_transparent_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_bottom_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..409d3cd
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_bottom_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_share_pack_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_share_pack_qntm_alpha.9.png
new file mode 100644
index 0000000..b07da0c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_share_pack_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..9d7b25f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-hdpi/ab_solid_shadow_qntm.9.png
deleted file mode 100644
index 717ec1a..0000000
--- a/core/res/res/drawable-hdpi/ab_solid_shadow_qntm.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_solid_shadow_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_solid_shadow_qntm_alpha.9.png
new file mode 100644
index 0000000..e49ad54
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_solid_shadow_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_solid_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_stacked_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..1222711
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_stacked_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ab_stacked_transparent_qntm_alpha.9.png b/core/res/res/drawable-hdpi/ab_stacked_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..d0fcc25
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ab_stacked_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_cab_done_qntm_alpha.9.png b/core/res/res/drawable-hdpi/btn_cab_done_qntm_alpha.9.png
new file mode 100644
index 0000000..992a8ff
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_cab_done_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_off_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_rating_star_off_qntm_alpha.png
new file mode 100644
index 0000000..51a895d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_rating_star_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_rating_star_on_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_rating_star_on_qntm_alpha.png
new file mode 100644
index 0000000..2f59488
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_rating_star_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_disabled_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_disabled_qntm_alpha.png
new file mode 100644
index 0000000..e0a2ba1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_disabled_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_off_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_off_qntm_alpha.png
new file mode 100644
index 0000000..d37e8ee
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_0_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_0_qntm_alpha.png
new file mode 100644
index 0000000..0c604d9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_0_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_1_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_1_qntm_alpha.png
new file mode 100644
index 0000000..2c3f4ff
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_1_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_2_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_2_qntm_alpha.png
new file mode 100644
index 0000000..991c50e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_2_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_media_route_on_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_media_route_on_qntm_alpha.png
new file mode 100644
index 0000000..05fb919
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_media_route_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_solid_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_bottom_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..219d311
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_bottom_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_bottom_transparent_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_bottom_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..bfdc933
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_bottom_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_share_pack_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_share_pack_qntm_alpha.9.png
new file mode 100644
index 0000000..f31730d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_share_pack_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..bd818b5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-mdpi/ab_solid_shadow_qntm.9.png
deleted file mode 100644
index c00c545..0000000
--- a/core/res/res/drawable-mdpi/ab_solid_shadow_qntm.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_solid_shadow_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_solid_shadow_qntm_alpha.9.png
new file mode 100644
index 0000000..ebdea00
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_solid_shadow_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_solid_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_stacked_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..41c7ce6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_stacked_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ab_stacked_transparent_qntm_alpha.9.png b/core/res/res/drawable-mdpi/ab_stacked_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..961a73e5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ab_stacked_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_cab_done_qntm_alpha.9.png b/core/res/res/drawable-mdpi/btn_cab_done_qntm_alpha.9.png
new file mode 100644
index 0000000..5903856
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_cab_done_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_off_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_rating_star_off_qntm_alpha.png
new file mode 100644
index 0000000..d38aed2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_rating_star_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_rating_star_on_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_rating_star_on_qntm_alpha.png
new file mode 100644
index 0000000..87dade3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_rating_star_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_disabled_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_disabled_qntm_alpha.png
new file mode 100644
index 0000000..ec43047
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_disabled_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_off_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_off_qntm_alpha.png
new file mode 100644
index 0000000..a652117
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_0_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_on_0_qntm_alpha.png
new file mode 100644
index 0000000..35d1c56
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_0_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_1_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_on_1_qntm_alpha.png
new file mode 100644
index 0000000..264188b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_1_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_2_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_on_2_qntm_alpha.png
new file mode 100644
index 0000000..06ae665
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_2_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_media_route_on_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_media_route_on_qntm_alpha.png
new file mode 100644
index 0000000..a69e301
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_media_route_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_solid_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_bottom_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..312f76c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_bottom_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_bottom_transparent_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_bottom_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..49e0a49
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_bottom_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_share_pack_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_share_pack_qntm_alpha.9.png
new file mode 100644
index 0000000..8337ffe
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_share_pack_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..fb0d0b6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm.9.png
deleted file mode 100644
index 1443b7f..0000000
--- a/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm_alpha.9.png
new file mode 100644
index 0000000..f51af63
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_solid_shadow_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_solid_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_stacked_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..6d87890
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_stacked_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ab_stacked_transparent_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/ab_stacked_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..58f3e0f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ab_stacked_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_cab_done_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/btn_cab_done_qntm_alpha.9.png
new file mode 100644
index 0000000..d0d0b1e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_cab_done_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_off_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_rating_star_off_qntm_alpha.png
new file mode 100644
index 0000000..33ec44c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_rating_star_on_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_rating_star_on_qntm_alpha.png
new file mode 100644
index 0000000..0166d70
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_rating_star_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_disabled_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_disabled_qntm_alpha.png
new file mode 100644
index 0000000..a020d64
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_disabled_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_off_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_off_qntm_alpha.png
new file mode 100644
index 0000000..e75ffb8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_0_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_on_0_qntm_alpha.png
new file mode 100644
index 0000000..1b9fc12
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_0_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_1_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_on_1_qntm_alpha.png
new file mode 100644
index 0000000..f63d47e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_1_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_2_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_on_2_qntm_alpha.png
new file mode 100644
index 0000000..fe005d9
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_2_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_media_route_on_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_media_route_on_qntm_alpha.png
new file mode 100644
index 0000000..ea86408
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_media_route_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_solid_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..65b8d4a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_bottom_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_bottom_transparent_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_bottom_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..a397baa
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_bottom_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_share_pack_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_share_pack_qntm_alpha.9.png
new file mode 100644
index 0000000..469f736
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_share_pack_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..b56fa4a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm.9.png b/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm.9.png
deleted file mode 100644
index e89c9fe..0000000
--- a/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm_alpha.9.png
new file mode 100644
index 0000000..e8a94dc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_solid_shadow_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_solid_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_solid_qntm_alpha.9.png
new file mode 100644
index 0000000..71b9737
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_stacked_solid_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_stacked_transparent_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_stacked_transparent_qntm_alpha.9.png
new file mode 100644
index 0000000..e2cc715
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ab_stacked_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png
index f220168..605d1de 100644
--- a/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/ab_transparent_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_cab_done_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/btn_cab_done_qntm_alpha.9.png
new file mode 100644
index 0000000..e1c55ad
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_cab_done_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_off_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_rating_star_off_qntm_alpha.png
new file mode 100644
index 0000000..4b49faf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_rating_star_on_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_rating_star_on_qntm_alpha.png
new file mode 100644
index 0000000..561d9ef
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_rating_star_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_disabled_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_qntm_alpha.png
new file mode 100644
index 0000000..6fad4a64
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_disabled_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_off_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_off_qntm_alpha.png
new file mode 100644
index 0000000..44d98d5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_off_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_0_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_qntm_alpha.png
new file mode 100644
index 0000000..c807b50
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_0_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_1_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_qntm_alpha.png
new file mode 100644
index 0000000..d54f44a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_1_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_2_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_qntm_alpha.png
new file mode 100644
index 0000000..17c1d99
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_2_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_media_route_on_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_media_route_on_qntm_alpha.png
new file mode 100644
index 0000000..906401e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_media_route_on_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_search_quantum_light.xml b/core/res/res/drawable/ab_bottom_solid_quantum.xml
similarity index 84%
copy from core/res/res/drawable/ic_menu_search_quantum_light.xml
copy to core/res/res/drawable/ab_bottom_solid_quantum.xml
index ba6efb6..848737e 100644
--- a/core/res/res/drawable/ic_menu_search_quantum_light.xml
+++ b/core/res/res/drawable/ab_bottom_solid_quantum.xml
@@ -15,5 +15,6 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_search_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:src="@drawable/ab_bottom_solid_qntm_alpha"
+ android:tint="?attr/colorBackground"
+ android:tintMode="multiply" />
diff --git a/core/res/res/drawable/ic_menu_search_quantum_light.xml b/core/res/res/drawable/ab_bottom_transparent_quantum.xml
similarity index 77%
copy from core/res/res/drawable/ic_menu_search_quantum_light.xml
copy to core/res/res/drawable/ab_bottom_transparent_quantum.xml
index ba6efb6..29df6b9 100644
--- a/core/res/res/drawable/ic_menu_search_quantum_light.xml
+++ b/core/res/res/drawable/ab_bottom_transparent_quantum.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!--
+ 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.
@@ -15,5 +16,6 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_search_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:src="@drawable/ab_bottom_transparent_qntm_alpha"
+ android:tint="?attr/colorBackground"
+ android:tintMode="multiply" />
diff --git a/core/res/res/drawable/ic_menu_search_quantum_light.xml b/core/res/res/drawable/ab_share_pack_quantum.xml
similarity index 85%
copy from core/res/res/drawable/ic_menu_search_quantum_light.xml
copy to core/res/res/drawable/ab_share_pack_quantum.xml
index ba6efb6..7d33ff4d 100644
--- a/core/res/res/drawable/ic_menu_search_quantum_light.xml
+++ b/core/res/res/drawable/ab_share_pack_quantum.xml
@@ -15,5 +15,5 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_search_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:src="@drawable/ab_share_pack_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_menu_search_quantum_light.xml b/core/res/res/drawable/ab_solid_quantum.xml
similarity index 85%
copy from core/res/res/drawable/ic_menu_search_quantum_light.xml
copy to core/res/res/drawable/ab_solid_quantum.xml
index ba6efb6..e56bb40 100644
--- a/core/res/res/drawable/ic_menu_search_quantum_light.xml
+++ b/core/res/res/drawable/ab_solid_quantum.xml
@@ -15,5 +15,6 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_search_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:src="@drawable/ab_solid_qntm_alpha"
+ android:tint="?attr/colorBackground"
+ android:tintMode="multiply" />
diff --git a/core/res/res/drawable/scrollbar_handle_quantum_light.xml b/core/res/res/drawable/ab_solid_shadow_quantum.xml
similarity index 85%
copy from core/res/res/drawable/scrollbar_handle_quantum_light.xml
copy to core/res/res/drawable/ab_solid_shadow_quantum.xml
index d4d4b8d..88e142a 100644
--- a/core/res/res/drawable/scrollbar_handle_quantum_light.xml
+++ b/core/res/res/drawable/ab_solid_shadow_quantum.xml
@@ -15,5 +15,5 @@
-->
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/scrollbar_handle_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:src="@drawable/ab_solid_shadow_qntm_alpha"
+ android:tint="@color/black" />
diff --git a/core/res/res/drawable/ic_menu_search_quantum_light.xml b/core/res/res/drawable/ab_stacked_solid_quantum.xml
similarity index 84%
copy from core/res/res/drawable/ic_menu_search_quantum_light.xml
copy to core/res/res/drawable/ab_stacked_solid_quantum.xml
index ba6efb6..df775af 100644
--- a/core/res/res/drawable/ic_menu_search_quantum_light.xml
+++ b/core/res/res/drawable/ab_stacked_solid_quantum.xml
@@ -15,5 +15,6 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_search_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:src="@drawable/ab_stacked_solid_qntm_alpha"
+ android:tint="?attr/colorBackground"
+ android:tintMode="multiply" />
diff --git a/core/res/res/drawable/ic_menu_search_quantum_light.xml b/core/res/res/drawable/ab_stacked_transparent_quantum.xml
similarity index 83%
copy from core/res/res/drawable/ic_menu_search_quantum_light.xml
copy to core/res/res/drawable/ab_stacked_transparent_quantum.xml
index ba6efb6..bdae6b9 100644
--- a/core/res/res/drawable/ic_menu_search_quantum_light.xml
+++ b/core/res/res/drawable/ab_stacked_transparent_quantum.xml
@@ -15,5 +15,6 @@
-->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_search_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:src="@drawable/ab_stacked_transparent_qntm_alpha"
+ android:tint="?attr/colorBackground"
+ android:tintMode="multiply" />
diff --git a/core/res/res/drawable/ab_transparent_quantum_light.xml b/core/res/res/drawable/ab_transparent_quantum.xml
similarity index 91%
rename from core/res/res/drawable/ab_transparent_quantum_light.xml
rename to core/res/res/drawable/ab_transparent_quantum.xml
index bc49848..495bfb6 100644
--- a/core/res/res/drawable/ab_transparent_quantum_light.xml
+++ b/core/res/res/drawable/ab_transparent_quantum.xml
@@ -16,4 +16,4 @@
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ab_transparent_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ab_transparent_quantum_dark.xml b/core/res/res/drawable/ab_transparent_quantum_dark.xml
deleted file mode 100644
index 9ac2fc0..0000000
--- a/core/res/res/drawable/ab_transparent_quantum_dark.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ab_transparent_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/activated_background_quantum_light.xml b/core/res/res/drawable/activated_background_quantum.xml
similarity index 79%
rename from core/res/res/drawable/activated_background_quantum_light.xml
rename to core/res/res/drawable/activated_background_quantum.xml
index 5d10ea2..e06c9f2 100644
--- a/core/res/res/drawable/activated_background_quantum_light.xml
+++ b/core/res/res/drawable/activated_background_quantum.xml
@@ -15,6 +15,10 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_activated="true" android:drawable="@color/control_activated_foreground_quantum_light" />
- <item android:drawable="@color/transparent" />
+ <item android:state_activated="true">
+ <color android:color="?attr/colorControlActivated" />
+ </item>
+ <item>
+ <color android:color="@color/transparent" />
+ </item>
</selector>
diff --git a/core/res/res/drawable/activated_background_quantum_dark.xml b/core/res/res/drawable/activated_background_quantum_dark.xml
deleted file mode 100644
index a9e3fea..0000000
--- a/core/res/res/drawable/activated_background_quantum_dark.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_activated="true" android:drawable="@color/control_activated_foreground_quantum_dark" />
- <item android:drawable="@color/transparent" />
-</selector>
diff --git a/core/res/res/drawable/item_background_borderless_quantum_dark.xml b/core/res/res/drawable/btn_borderless_quantum.xml
similarity index 82%
copy from core/res/res/drawable/item_background_borderless_quantum_dark.xml
copy to core/res/res/drawable/btn_borderless_quantum.xml
index 3f32850..2e3c515 100644
--- a/core/res/res/drawable/item_background_borderless_quantum_dark.xml
+++ b/core/res/res/drawable/btn_borderless_quantum.xml
@@ -15,4 +15,7 @@
-->
<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="@color/lighter_gray" />
+ android:tint="?attr/colorButtonPressed">
+ <item android:id="@id/mask"
+ android:drawable="@drawable/btn_qntm_alpha" />
+</touch-feedback>
diff --git a/core/res/res/drawable/btn_borderless_quantum_dark.xml b/core/res/res/drawable/btn_borderless_quantum_dark.xml
deleted file mode 100644
index 2c0d3b7..0000000
--- a/core/res/res/drawable/btn_borderless_quantum_dark.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="@color/btn_default_pressed_quantum_dark"
- android:mask="@drawable/btn_qntm_alpha" />
diff --git a/core/res/res/drawable/btn_borderless_quantum_light.xml b/core/res/res/drawable/btn_borderless_quantum_light.xml
deleted file mode 100644
index 2faec20..0000000
--- a/core/res/res/drawable/btn_borderless_quantum_light.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="@color/btn_default_pressed_quantum_light"
- android:mask="@drawable/btn_qntm_alpha" />
diff --git a/core/res/res/drawable/btn_cab_done_quantum.xml b/core/res/res/drawable/btn_cab_done_quantum.xml
new file mode 100644
index 0000000..c03ab0a
--- /dev/null
+++ b/core/res/res/drawable/btn_cab_done_quantum.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true">
+ <item android:state_pressed="true">
+ <color android:color="?attr/colorButtonPressed" />
+ </item>
+ <item android:state_focused="true" android:state_enabled="true">
+ <nine-patch android:src="@drawable/btn_cab_done_qntm_alpha"
+ android:tint="?attr/colorButtonPressed" />
+ </item>
+ <item android:state_enabled="true">
+ <nine-patch android:src="@drawable/btn_cab_done_qntm_alpha"
+ android:tint="?attr/colorButtonNormal" />
+ </item>
+</selector>
diff --git a/core/res/res/drawable/btn_check_quantum_dark.xml b/core/res/res/drawable/btn_check_quantum.xml
similarity index 79%
rename from core/res/res/drawable/btn_check_quantum_dark.xml
rename to core/res/res/drawable/btn_check_quantum.xml
index a35bec4..6ceba60 100644
--- a/core/res/res/drawable/btn_check_quantum_dark.xml
+++ b/core/res/res/drawable/btn_check_quantum.xml
@@ -17,18 +17,18 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:state_pressed="true">
<bitmap android:src="@drawable/btn_check_on_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item android:state_checked="true">
<bitmap android:src="@drawable/btn_check_on_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item android:state_pressed="true">
<bitmap android:src="@drawable/btn_check_off_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item>
<bitmap android:src="@drawable/btn_check_off_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
</item>
</selector>
diff --git a/core/res/res/drawable/btn_check_quantum_light.xml b/core/res/res/drawable/btn_check_quantum_light.xml
deleted file mode 100644
index 8588fce..0000000
--- a/core/res/res/drawable/btn_check_quantum_light.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_checked="true" android:state_pressed="true">
- <bitmap android:src="@drawable/btn_check_on_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item android:state_checked="true">
- <bitmap android:src="@drawable/btn_check_on_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item android:state_pressed="true">
- <bitmap android:src="@drawable/btn_check_off_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item>
- <bitmap android:src="@drawable/btn_check_off_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
- </item>
-</selector>
diff --git a/core/res/res/drawable/btn_color_quantum_dark.xml b/core/res/res/drawable/btn_color_quantum.xml
similarity index 84%
rename from core/res/res/drawable/btn_color_quantum_dark.xml
rename to core/res/res/drawable/btn_color_quantum.xml
index 0507755..e923003 100644
--- a/core/res/res/drawable/btn_color_quantum_dark.xml
+++ b/core/res/res/drawable/btn_color_quantum.xml
@@ -15,15 +15,15 @@
-->
<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="@color/theme_color_300">
+ android:tint="?attr/colorButtonPressedColored">
<selector>
<item android:state_enabled="false">
<nine-patch android:src="@drawable/btn_qntm_alpha"
- android:tint="@color/btn_default_normal_quantum_dark" />
+ android:tint="?attr/colorButtonNormal" />
</item>
<item>
<nine-patch android:src="@drawable/btn_qntm_alpha"
- android:tint="@color/theme_color_500" />
+ android:tint="?attr/colorButtonNormalColored" />
</item>
</selector>
</touch-feedback>
diff --git a/core/res/res/drawable/btn_color_quantum_light.xml b/core/res/res/drawable/btn_color_quantum_light.xml
deleted file mode 100644
index 9166b8d..0000000
--- a/core/res/res/drawable/btn_color_quantum_light.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="@color/theme_color_700">
- <selector>
- <item android:state_enabled="false">
- <nine-patch android:src="@drawable/btn_qntm_alpha"
- android:tint="@color/btn_default_normal_quantum_dark" />
- </item>
- <item>
- <nine-patch android:src="@drawable/btn_qntm_alpha"
- android:tint="@color/theme_color_500" />
- </item>
- </selector>
-</touch-feedback>
diff --git a/core/res/res/drawable/btn_default_quantum_light.xml b/core/res/res/drawable/btn_default_quantum.xml
similarity index 80%
rename from core/res/res/drawable/btn_default_quantum_light.xml
rename to core/res/res/drawable/btn_default_quantum.xml
index c6e828c..2919621 100644
--- a/core/res/res/drawable/btn_default_quantum_light.xml
+++ b/core/res/res/drawable/btn_default_quantum.xml
@@ -15,7 +15,9 @@
-->
<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="@color/btn_default_pressed_quantum_light">
- <nine-patch android:src="@drawable/btn_qntm_alpha"
- android:tint="@color/btn_default_normal_quantum_light" />
+ android:tint="?attr/colorButtonPressed">
+ <item>
+ <nine-patch android:src="@drawable/btn_qntm_alpha"
+ android:tint="?attr/colorButtonNormal" />
+ </item>
</touch-feedback>
diff --git a/core/res/res/drawable/btn_default_quantum_dark.xml b/core/res/res/drawable/btn_default_quantum_dark.xml
deleted file mode 100644
index 29c3e24..0000000
--- a/core/res/res/drawable/btn_default_quantum_dark.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="@color/btn_default_pressed_quantum_dark">
- <nine-patch android:src="@drawable/btn_qntm_alpha"
- android:tint="@color/btn_default_normal_quantum_dark" />
-</touch-feedback>
diff --git a/core/res/res/drawable/btn_radio_quantum_dark.xml b/core/res/res/drawable/btn_radio_quantum.xml
similarity index 80%
rename from core/res/res/drawable/btn_radio_quantum_dark.xml
rename to core/res/res/drawable/btn_radio_quantum.xml
index 54f4f9a..152e3d3 100644
--- a/core/res/res/drawable/btn_radio_quantum_dark.xml
+++ b/core/res/res/drawable/btn_radio_quantum.xml
@@ -17,18 +17,18 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:state_enabled="true" android:state_pressed="true">
<bitmap android:src="@drawable/btn_radio_on_pressed_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item android:state_checked="true">
<bitmap android:src="@drawable/btn_radio_on_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item android:state_enabled="true" android:state_pressed="true">
<bitmap android:src="@drawable/btn_radio_off_pressed_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item>
<bitmap android:src="@drawable/btn_radio_off_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
</item>
</selector>
diff --git a/core/res/res/drawable/btn_radio_quantum_light.xml b/core/res/res/drawable/btn_radio_quantum_light.xml
deleted file mode 100644
index c1ace70..0000000
--- a/core/res/res/drawable/btn_radio_quantum_light.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_checked="true" android:state_enabled="true" android:state_pressed="true">
- <bitmap android:src="@drawable/btn_radio_on_pressed_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item android:state_checked="true">
- <bitmap android:src="@drawable/btn_radio_on_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item android:state_enabled="true" android:state_pressed="true">
- <bitmap android:src="@drawable/btn_radio_off_pressed_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item>
- <bitmap android:src="@drawable/btn_radio_off_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
- </item>
-</selector>
diff --git a/core/res/res/drawable/btn_star_quantum_light.xml b/core/res/res/drawable/btn_star_quantum.xml
similarity index 81%
rename from core/res/res/drawable/btn_star_quantum_light.xml
rename to core/res/res/drawable/btn_star_quantum.xml
index df2cc91..512cd57 100644
--- a/core/res/res/drawable/btn_star_quantum_light.xml
+++ b/core/res/res/drawable/btn_star_quantum.xml
@@ -17,14 +17,14 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<bitmap android:src="@drawable/btn_star_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item android:state_pressed="true">
<bitmap android:src="@drawable/btn_star_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item>
<bitmap android:src="@drawable/btn_star_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:tint="?attr/colorControlNormal" />
</item>
</selector>
diff --git a/core/res/res/drawable/btn_star_quantum_dark.xml b/core/res/res/drawable/btn_star_quantum_dark.xml
deleted file mode 100644
index 7b26a3c..0000000
--- a/core/res/res/drawable/btn_star_quantum_dark.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_checked="true">
- <bitmap android:src="@drawable/btn_star_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
- </item>
- <item android:state_pressed="true">
- <bitmap android:src="@drawable/btn_star_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
- </item>
- <item>
- <bitmap android:src="@drawable/btn_star_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
- </item>
-</selector>
diff --git a/core/res/res/drawable/edit_text_quantum_dark.xml b/core/res/res/drawable/edit_text_quantum.xml
similarity index 77%
rename from core/res/res/drawable/edit_text_quantum_dark.xml
rename to core/res/res/drawable/edit_text_quantum.xml
index ea3fc52..d1f9831 100644
--- a/core/res/res/drawable/edit_text_quantum_dark.xml
+++ b/core/res/res/drawable/edit_text_quantum.xml
@@ -17,26 +17,26 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false" android:state_enabled="true">
<nine-patch android:src="@drawable/textfield_default_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
</item>
<item android:state_window_focused="false" android:state_enabled="false">
<nine-patch android:src="@drawable/textfield_default_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
</item>
<item android:state_enabled="true" android:state_focused="true">
<nine-patch android:src="@drawable/textfield_activated_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item android:state_enabled="true" android:state_activated="true">
<nine-patch android:src="@drawable/textfield_activated_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item android:state_enabled="true">
<nine-patch android:src="@drawable/textfield_default_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
</item>
<item>
<nine-patch android:src="@drawable/textfield_default_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
</item>
</selector>
diff --git a/core/res/res/drawable/edit_text_quantum_light.xml b/core/res/res/drawable/edit_text_quantum_light.xml
deleted file mode 100644
index dd7fe53..0000000
--- a/core/res/res/drawable/edit_text_quantum_light.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_window_focused="false" android:state_enabled="true">
- <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
- </item>
- <item android:state_window_focused="false" android:state_enabled="false">
- <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
- </item>
- <item android:state_enabled="true" android:state_focused="true">
- <nine-patch android:src="@drawable/textfield_activated_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item android:state_enabled="true" android:state_activated="true">
- <nine-patch android:src="@drawable/textfield_activated_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item android:state_enabled="true">
- <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
- </item>
- <item>
- <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
- </item>
-</selector>
diff --git a/core/res/res/drawable/expander_group_quantum_dark.xml b/core/res/res/drawable/expander_group_quantum.xml
similarity index 86%
rename from core/res/res/drawable/expander_group_quantum_dark.xml
rename to core/res/res/drawable/expander_group_quantum.xml
index 7250e01..48245ea 100644
--- a/core/res/res/drawable/expander_group_quantum_dark.xml
+++ b/core/res/res/drawable/expander_group_quantum.xml
@@ -17,10 +17,10 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_expanded="true">
<nine-patch android:src="@drawable/expander_close_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
</item>
<item>
<nine-patch android:src="@drawable/expander_open_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
</item>
</selector>
diff --git a/core/res/res/drawable/expander_group_quantum_light.xml b/core/res/res/drawable/expander_group_quantum_light.xml
deleted file mode 100644
index 62af983..0000000
--- a/core/res/res/drawable/expander_group_quantum_light.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_expanded="true">
- <nine-patch android:src="@drawable/expander_close_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
- </item>
- <item>
- <nine-patch android:src="@drawable/expander_open_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
- </item>
-</selector>
diff --git a/core/res/res/drawable/fastscroll_thumb_quantum_dark.xml b/core/res/res/drawable/fastscroll_thumb_quantum.xml
similarity index 85%
rename from core/res/res/drawable/fastscroll_thumb_quantum_dark.xml
rename to core/res/res/drawable/fastscroll_thumb_quantum.xml
index 53c7fdd..496b2ae 100644
--- a/core/res/res/drawable/fastscroll_thumb_quantum_dark.xml
+++ b/core/res/res/drawable/fastscroll_thumb_quantum.xml
@@ -17,10 +17,10 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<bitmap android:src="@drawable/fastscroll_thumb_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item>
<bitmap android:src="@drawable/fastscroll_thumb_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
</item>
</selector>
diff --git a/core/res/res/drawable/fastscroll_thumb_quantum_light.xml b/core/res/res/drawable/fastscroll_thumb_quantum_light.xml
deleted file mode 100644
index 3bc87e9..0000000
--- a/core/res/res/drawable/fastscroll_thumb_quantum_light.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true">
- <bitmap android:src="@drawable/fastscroll_thumb_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item>
- <bitmap android:src="@drawable/fastscroll_thumb_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
- </item>
-</selector>
diff --git a/core/res/res/drawable/fastscroll_track_quantum_dark.xml b/core/res/res/drawable/fastscroll_track_quantum.xml
similarity index 91%
rename from core/res/res/drawable/fastscroll_track_quantum_dark.xml
rename to core/res/res/drawable/fastscroll_track_quantum.xml
index 0ae57d2..59c35db 100644
--- a/core/res/res/drawable/fastscroll_track_quantum_dark.xml
+++ b/core/res/res/drawable/fastscroll_track_quantum.xml
@@ -16,4 +16,4 @@
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/fastscroll_track_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/fastscroll_track_quantum_light.xml b/core/res/res/drawable/fastscroll_track_quantum_light.xml
deleted file mode 100644
index 627c079..0000000
--- a/core/res/res/drawable/fastscroll_track_quantum_light.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/fastscroll_track_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_ab_back_quantum_dark.xml b/core/res/res/drawable/ic_ab_back_quantum.xml
similarity index 92%
rename from core/res/res/drawable/ic_ab_back_quantum_dark.xml
rename to core/res/res/drawable/ic_ab_back_quantum.xml
index 628d53e..65c7584 100644
--- a/core/res/res/drawable/ic_ab_back_quantum_dark.xml
+++ b/core/res/res/drawable/ic_ab_back_quantum.xml
@@ -17,4 +17,4 @@
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_ab_back_qntm_am_alpha"
android:autoMirrored="true"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_ab_back_quantum_light.xml b/core/res/res/drawable/ic_ab_back_quantum_light.xml
deleted file mode 100644
index 01f5362..0000000
--- a/core/res/res/drawable/ic_ab_back_quantum_light.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_ab_back_qntm_am_alpha"
- android:autoMirrored="true"
- android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/ic_cab_done_quantum_light.xml b/core/res/res/drawable/ic_cab_done_quantum.xml
similarity index 91%
rename from core/res/res/drawable/ic_cab_done_quantum_light.xml
rename to core/res/res/drawable/ic_cab_done_quantum.xml
index d70a3f1..97495a8 100644
--- a/core/res/res/drawable/ic_cab_done_quantum_light.xml
+++ b/core/res/res/drawable/ic_cab_done_quantum.xml
@@ -16,4 +16,4 @@
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_cab_done_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_cab_done_quantum_dark.xml b/core/res/res/drawable/ic_cab_done_quantum_dark.xml
deleted file mode 100644
index 472996e..0000000
--- a/core/res/res/drawable/ic_cab_done_quantum_dark.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_cab_done_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_dialog_alert_quantum_dark.xml b/core/res/res/drawable/ic_dialog_alert_quantum.xml
similarity index 91%
rename from core/res/res/drawable/ic_dialog_alert_quantum_dark.xml
rename to core/res/res/drawable/ic_dialog_alert_quantum.xml
index 8b8cb0c..05f3630 100644
--- a/core/res/res/drawable/ic_dialog_alert_quantum_dark.xml
+++ b/core/res/res/drawable/ic_dialog_alert_quantum.xml
@@ -16,4 +16,4 @@
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_dialog_alert_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_dialog_alert_quantum_light.xml b/core/res/res/drawable/ic_dialog_alert_quantum_light.xml
deleted file mode 100644
index 8b8cb0c..0000000
--- a/core/res/res/drawable/ic_dialog_alert_quantum_light.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_dialog_alert_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_find_next_quantum_light.xml b/core/res/res/drawable/ic_find_next_quantum.xml
similarity index 91%
rename from core/res/res/drawable/ic_find_next_quantum_light.xml
rename to core/res/res/drawable/ic_find_next_quantum.xml
index 9c20327..fee196c 100644
--- a/core/res/res/drawable/ic_find_next_quantum_light.xml
+++ b/core/res/res/drawable/ic_find_next_quantum.xml
@@ -16,4 +16,4 @@
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_find_next_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_find_next_quantum_dark.xml b/core/res/res/drawable/ic_find_next_quantum_dark.xml
deleted file mode 100644
index 929bea3..0000000
--- a/core/res/res/drawable/ic_find_next_quantum_dark.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_find_next_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_find_previous_quantum_light.xml b/core/res/res/drawable/ic_find_previous_quantum.xml
similarity index 91%
rename from core/res/res/drawable/ic_find_previous_quantum_light.xml
rename to core/res/res/drawable/ic_find_previous_quantum.xml
index b037094..28f887a 100644
--- a/core/res/res/drawable/ic_find_previous_quantum_light.xml
+++ b/core/res/res/drawable/ic_find_previous_quantum.xml
@@ -16,4 +16,4 @@
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_find_previous_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_find_previous_quantum_dark.xml b/core/res/res/drawable/ic_find_previous_quantum_dark.xml
deleted file mode 100644
index e944223..0000000
--- a/core/res/res/drawable/ic_find_previous_quantum_dark.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_find_previous_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_media_route_connecting_quantum.xml b/core/res/res/drawable/ic_media_route_connecting_quantum.xml
new file mode 100644
index 0000000..0029dd4
--- /dev/null
+++ b/core/res/res/drawable/ic_media_route_connecting_quantum.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+ android:oneshot="false">
+ <item android:duration="500">
+ <bitmap android:src="@drawable/ic_media_route_on_0_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ <item android:duration="500">
+ <bitmap android:src="@drawable/ic_media_route_on_1_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ <item android:duration="500">
+ <bitmap android:src="@drawable/ic_media_route_on_2_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ <item android:duration="500">
+ <bitmap android:src="@drawable/ic_media_route_on_1_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+</animation-list>
diff --git a/core/res/res/drawable/ic_media_route_quantum.xml b/core/res/res/drawable/ic_media_route_quantum.xml
new file mode 100644
index 0000000..16b63d4
--- /dev/null
+++ b/core/res/res/drawable/ic_media_route_quantum.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_checked="true" android:state_enabled="true"
+ android:drawable="@android:drawable/ic_media_route_connecting_quantum" />
+ <item android:state_activated="true" android:state_enabled="true">
+ <bitmap android:src="@android:drawable/ic_media_route_on_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ <item android:state_enabled="true">
+ <bitmap android:src="@android:drawable/ic_media_route_off_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ <item>
+ <bitmap android:src="@android:drawable/ic_media_route_disabled_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+</selector>
diff --git a/core/res/res/drawable/ic_menu_copy_quantum_dark.xml b/core/res/res/drawable/ic_menu_copy_quantum.xml
similarity index 92%
rename from core/res/res/drawable/ic_menu_copy_quantum_dark.xml
rename to core/res/res/drawable/ic_menu_copy_quantum.xml
index 285b752..5f6ce51 100644
--- a/core/res/res/drawable/ic_menu_copy_quantum_dark.xml
+++ b/core/res/res/drawable/ic_menu_copy_quantum.xml
@@ -16,5 +16,5 @@
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_menu_copy_qntm_am_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark"
+ android:tint="?attr/colorControlNormal"
android:autoMirrored="true" />
diff --git a/core/res/res/drawable/ic_menu_copy_quantum_light.xml b/core/res/res/drawable/ic_menu_copy_quantum_light.xml
deleted file mode 100644
index a40b219..0000000
--- a/core/res/res/drawable/ic_menu_copy_quantum_light.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_copy_qntm_am_alpha"
- android:tint="@color/control_normal_foreground_quantum_light"
- android:autoMirrored="true" />
diff --git a/core/res/res/drawable/ic_menu_cut_quantum_dark.xml b/core/res/res/drawable/ic_menu_cut_quantum.xml
similarity index 91%
rename from core/res/res/drawable/ic_menu_cut_quantum_dark.xml
rename to core/res/res/drawable/ic_menu_cut_quantum.xml
index 563400b..1e4996e 100644
--- a/core/res/res/drawable/ic_menu_cut_quantum_dark.xml
+++ b/core/res/res/drawable/ic_menu_cut_quantum.xml
@@ -16,4 +16,4 @@
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_menu_cut_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_menu_cut_quantum_light.xml b/core/res/res/drawable/ic_menu_cut_quantum_light.xml
deleted file mode 100644
index 36c9442..0000000
--- a/core/res/res/drawable/ic_menu_cut_quantum_light.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_cut_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/ic_menu_find_quantum_light.xml b/core/res/res/drawable/ic_menu_find_quantum.xml
similarity index 91%
rename from core/res/res/drawable/ic_menu_find_quantum_light.xml
rename to core/res/res/drawable/ic_menu_find_quantum.xml
index 9b3bd73..a69c673 100644
--- a/core/res/res/drawable/ic_menu_find_quantum_light.xml
+++ b/core/res/res/drawable/ic_menu_find_quantum.xml
@@ -16,4 +16,4 @@
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_menu_find_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_menu_find_quantum_dark.xml b/core/res/res/drawable/ic_menu_find_quantum_dark.xml
deleted file mode 100644
index 8803463..0000000
--- a/core/res/res/drawable/ic_menu_find_quantum_dark.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_find_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_menu_moreoverflow_quantum_light.xml b/core/res/res/drawable/ic_menu_moreoverflow_quantum.xml
similarity index 91%
rename from core/res/res/drawable/ic_menu_moreoverflow_quantum_light.xml
rename to core/res/res/drawable/ic_menu_moreoverflow_quantum.xml
index e15eaec..7d3fcac 100644
--- a/core/res/res/drawable/ic_menu_moreoverflow_quantum_light.xml
+++ b/core/res/res/drawable/ic_menu_moreoverflow_quantum.xml
@@ -16,4 +16,4 @@
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_menu_moreoverflow_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_menu_moreoverflow_quantum_dark.xml b/core/res/res/drawable/ic_menu_moreoverflow_quantum_dark.xml
deleted file mode 100644
index 9f39a68..0000000
--- a/core/res/res/drawable/ic_menu_moreoverflow_quantum_dark.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_moreoverflow_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_menu_paste_quantum_light.xml b/core/res/res/drawable/ic_menu_paste_quantum.xml
similarity index 92%
rename from core/res/res/drawable/ic_menu_paste_quantum_light.xml
rename to core/res/res/drawable/ic_menu_paste_quantum.xml
index 155ec34..f590904 100644
--- a/core/res/res/drawable/ic_menu_paste_quantum_light.xml
+++ b/core/res/res/drawable/ic_menu_paste_quantum.xml
@@ -16,5 +16,5 @@
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_menu_paste_qntm_am_alpha"
- android:tint="@color/control_normal_foreground_quantum_light"
+ android:tint="?attr/colorControlNormal"
android:autoMirrored="true" />
diff --git a/core/res/res/drawable/ic_menu_paste_quantum_dark.xml b/core/res/res/drawable/ic_menu_paste_quantum_dark.xml
deleted file mode 100644
index 7033404..0000000
--- a/core/res/res/drawable/ic_menu_paste_quantum_dark.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_paste_qntm_am_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark"
- android:autoMirrored="true" />
diff --git a/core/res/res/drawable/ic_menu_search_quantum_light.xml b/core/res/res/drawable/ic_menu_search_quantum.xml
similarity index 91%
rename from core/res/res/drawable/ic_menu_search_quantum_light.xml
rename to core/res/res/drawable/ic_menu_search_quantum.xml
index ba6efb6..2ca8c20 100644
--- a/core/res/res/drawable/ic_menu_search_quantum_light.xml
+++ b/core/res/res/drawable/ic_menu_search_quantum.xml
@@ -16,4 +16,4 @@
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_menu_search_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_menu_search_quantum_dark.xml b/core/res/res/drawable/ic_menu_search_quantum_dark.xml
deleted file mode 100644
index 1c6efcd..0000000
--- a/core/res/res/drawable/ic_menu_search_quantum_dark.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_search_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/ic_menu_selectall_quantum_dark.xml b/core/res/res/drawable/ic_menu_selectall_quantum.xml
similarity index 91%
rename from core/res/res/drawable/ic_menu_selectall_quantum_dark.xml
rename to core/res/res/drawable/ic_menu_selectall_quantum.xml
index c1d3e69..fd72ebf 100644
--- a/core/res/res/drawable/ic_menu_selectall_quantum_dark.xml
+++ b/core/res/res/drawable/ic_menu_selectall_quantum.xml
@@ -16,4 +16,4 @@
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_menu_selectall_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_menu_selectall_quantum_light.xml b/core/res/res/drawable/ic_menu_selectall_quantum_light.xml
deleted file mode 100644
index 4de8962..0000000
--- a/core/res/res/drawable/ic_menu_selectall_quantum_light.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_selectall_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/ic_menu_share_quantum_dark.xml b/core/res/res/drawable/ic_menu_share_quantum.xml
similarity index 91%
rename from core/res/res/drawable/ic_menu_share_quantum_dark.xml
rename to core/res/res/drawable/ic_menu_share_quantum.xml
index a7c5afc..f44e06c 100644
--- a/core/res/res/drawable/ic_menu_share_quantum_dark.xml
+++ b/core/res/res/drawable/ic_menu_share_quantum.xml
@@ -16,4 +16,4 @@
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_menu_share_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_menu_share_quantum_light.xml b/core/res/res/drawable/ic_menu_share_quantum_light.xml
deleted file mode 100644
index 9257c25..0000000
--- a/core/res/res/drawable/ic_menu_share_quantum_light.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_share_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
diff --git a/core/res/res/drawable/item_background_borderless_quantum_light.xml b/core/res/res/drawable/item_background_borderless_quantum_light.xml
deleted file mode 100644
index 09f6ae9..0000000
--- a/core/res/res/drawable/item_background_borderless_quantum_light.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="@color/darker_gray" />
diff --git a/core/res/res/drawable/item_background_borderless_quantum_dark.xml b/core/res/res/drawable/item_background_quantum.xml
similarity index 90%
rename from core/res/res/drawable/item_background_borderless_quantum_dark.xml
rename to core/res/res/drawable/item_background_quantum.xml
index 3f32850..11e1f67 100644
--- a/core/res/res/drawable/item_background_borderless_quantum_dark.xml
+++ b/core/res/res/drawable/item_background_quantum.xml
@@ -15,4 +15,5 @@
-->
<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="@color/lighter_gray" />
+ android:tint="?attr/colorButtonPressed"
+ android:pinned="true" />
diff --git a/core/res/res/drawable/item_background_quantum_dark.xml b/core/res/res/drawable/item_background_quantum_dark.xml
deleted file mode 100644
index 3f32850..0000000
--- a/core/res/res/drawable/item_background_quantum_dark.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="@color/lighter_gray" />
diff --git a/core/res/res/drawable/item_background_quantum_light.xml b/core/res/res/drawable/item_background_quantum_light.xml
deleted file mode 100644
index 09f6ae9..0000000
--- a/core/res/res/drawable/item_background_quantum_light.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="@color/darker_gray" />
diff --git a/core/res/res/drawable/list_divider_quantum_light.xml b/core/res/res/drawable/list_divider_quantum.xml
similarity index 91%
rename from core/res/res/drawable/list_divider_quantum_light.xml
rename to core/res/res/drawable/list_divider_quantum.xml
index d312e2d..e3d4ba2 100644
--- a/core/res/res/drawable/list_divider_quantum_light.xml
+++ b/core/res/res/drawable/list_divider_quantum.xml
@@ -16,4 +16,4 @@
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/list_divider_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/list_divider_quantum_dark.xml b/core/res/res/drawable/list_divider_quantum_dark.xml
deleted file mode 100644
index 9d05b2f..0000000
--- a/core/res/res/drawable/list_divider_quantum_dark.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/list_divider_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/list_section_divider_quantum_light.xml b/core/res/res/drawable/list_section_divider_quantum.xml
similarity index 91%
rename from core/res/res/drawable/list_section_divider_quantum_light.xml
rename to core/res/res/drawable/list_section_divider_quantum.xml
index 98ede38..87a1439 100644
--- a/core/res/res/drawable/list_section_divider_quantum_light.xml
+++ b/core/res/res/drawable/list_section_divider_quantum.xml
@@ -16,4 +16,4 @@
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/list_section_divider_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/list_section_divider_quantum_dark.xml b/core/res/res/drawable/list_section_divider_quantum_dark.xml
deleted file mode 100644
index 6344c7e..0000000
--- a/core/res/res/drawable/list_section_divider_quantum_dark.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/list_section_divider_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml b/core/res/res/drawable/notification_icon_legacy_bg.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/notification_icon_legacy_bg.xml
rename to core/res/res/drawable/notification_icon_legacy_bg.xml
diff --git a/packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml b/core/res/res/drawable/notification_icon_legacy_bg_inset.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/notification_icon_legacy_bg_inset.xml
rename to core/res/res/drawable/notification_icon_legacy_bg_inset.xml
diff --git a/core/res/res/drawable/notification_quantum_background.xml b/core/res/res/drawable/notification_quantum_background.xml
index f33e2e3..7b508a9 100644
--- a/core/res/res/drawable/notification_quantum_background.xml
+++ b/core/res/res/drawable/notification_quantum_background.xml
@@ -17,5 +17,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ffffffff" />
- <corners android:radius="2dp" />
+ <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
</shape>
\ No newline at end of file
diff --git a/core/res/res/drawable/progress_horizontal_quantum_dark.xml b/core/res/res/drawable/progress_horizontal_quantum.xml
similarity index 83%
rename from core/res/res/drawable/progress_horizontal_quantum_dark.xml
rename to core/res/res/drawable/progress_horizontal_quantum.xml
index fb4b67e..1c2d494 100644
--- a/core/res/res/drawable/progress_horizontal_quantum_dark.xml
+++ b/core/res/res/drawable/progress_horizontal_quantum.xml
@@ -17,18 +17,18 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@id/background">
<nine-patch android:src="@drawable/progress_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
</item>
<item android:id="@id/secondaryProgress">
<scale android:scaleWidth="100%">
<nine-patch android:src="@drawable/progress_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</scale>
</item>
<item android:id="@id/progress">
<scale android:scaleWidth="100%">
<nine-patch android:src="@drawable/progress_primary_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</scale>
</item>
</layer-list>
diff --git a/core/res/res/drawable/progress_horizontal_quantum_light.xml b/core/res/res/drawable/progress_horizontal_quantum_light.xml
deleted file mode 100644
index 1ceb2e2..0000000
--- a/core/res/res/drawable/progress_horizontal_quantum_light.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@id/background">
- <nine-patch android:src="@drawable/progress_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
- </item>
- <item android:id="@id/secondaryProgress">
- <scale android:scaleWidth="100%">
- <nine-patch android:src="@drawable/progress_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </scale>
- </item>
- <item android:id="@id/progress">
- <scale android:scaleWidth="100%">
- <nine-patch android:src="@drawable/progress_primary_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </scale>
- </item>
-</layer-list>
diff --git a/core/res/res/drawable/scrubber_progress_horizontal_quantum_light.xml b/core/res/res/drawable/ratingbar_full_empty_quantum.xml
similarity index 73%
copy from core/res/res/drawable/scrubber_progress_horizontal_quantum_light.xml
copy to core/res/res/drawable/ratingbar_full_empty_quantum.xml
index 053f542..e5e4315 100644
--- a/core/res/res/drawable/scrubber_progress_horizontal_quantum_light.xml
+++ b/core/res/res/drawable/ratingbar_full_empty_quantum.xml
@@ -16,11 +16,11 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
- <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
+ <bitmap android:src="@drawable/btn_rating_star_off_qntm_alpha"
+ android:tint="?attr/colorControlActivated" />
</item>
<item>
- <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ <bitmap android:src="@drawable/btn_rating_star_off_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
</item>
</selector>
diff --git a/core/res/res/drawable/scrubber_progress_horizontal_quantum_light.xml b/core/res/res/drawable/ratingbar_full_filled_quantum.xml
similarity index 73%
copy from core/res/res/drawable/scrubber_progress_horizontal_quantum_light.xml
copy to core/res/res/drawable/ratingbar_full_filled_quantum.xml
index 053f542..ad3aa5d 100644
--- a/core/res/res/drawable/scrubber_progress_horizontal_quantum_light.xml
+++ b/core/res/res/drawable/ratingbar_full_filled_quantum.xml
@@ -16,11 +16,11 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
- <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
+ <bitmap android:src="@drawable/btn_rating_star_on_qntm_alpha"
+ android:tint="?attr/colorControlActivated" />
</item>
<item>
- <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ <bitmap android:src="@drawable/btn_rating_star_on_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
</item>
</selector>
diff --git a/core/res/res/drawable/ic_menu_search_quantum_light.xml b/core/res/res/drawable/ratingbar_full_quantum.xml
similarity index 62%
copy from core/res/res/drawable/ic_menu_search_quantum_light.xml
copy to core/res/res/drawable/ratingbar_full_quantum.xml
index ba6efb6..143e7c2 100644
--- a/core/res/res/drawable/ic_menu_search_quantum_light.xml
+++ b/core/res/res/drawable/ratingbar_full_quantum.xml
@@ -14,6 +14,11 @@
limitations under the License.
-->
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_menu_search_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@id/background"
+ android:drawable="@drawable/ratingbar_full_empty_quantum" />
+ <item android:id="@id/secondaryProgress"
+ android:drawable="@drawable/ratingbar_full_empty_quantum" />
+ <item android:id="@id/progress"
+ android:drawable="@drawable/ratingbar_full_filled_quantum" />
+</layer-list>
diff --git a/core/res/res/drawable/scrollbar_handle_quantum_light.xml b/core/res/res/drawable/scrollbar_handle_quantum.xml
similarity index 91%
rename from core/res/res/drawable/scrollbar_handle_quantum_light.xml
rename to core/res/res/drawable/scrollbar_handle_quantum.xml
index d4d4b8d..f2de252 100644
--- a/core/res/res/drawable/scrollbar_handle_quantum_light.xml
+++ b/core/res/res/drawable/scrollbar_handle_quantum.xml
@@ -16,4 +16,4 @@
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/scrollbar_handle_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/scrollbar_handle_quantum_dark.xml b/core/res/res/drawable/scrollbar_handle_quantum_dark.xml
deleted file mode 100644
index 2d4e37d..0000000
--- a/core/res/res/drawable/scrollbar_handle_quantum_dark.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/scrollbar_handle_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
diff --git a/core/res/res/drawable/scrubber_control_selector_quantum_light.xml b/core/res/res/drawable/scrubber_control_selector_quantum.xml
similarity index 86%
rename from core/res/res/drawable/scrubber_control_selector_quantum_light.xml
rename to core/res/res/drawable/scrubber_control_selector_quantum.xml
index 8d009b7..e31c2c1 100644
--- a/core/res/res/drawable/scrubber_control_selector_quantum_light.xml
+++ b/core/res/res/drawable/scrubber_control_selector_quantum.xml
@@ -17,10 +17,10 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:state_pressed="true">
<bitmap android:src="@drawable/scrubber_control_on_pressed_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item>
<bitmap android:src="@drawable/scrubber_control_on_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:tint="?attr/colorControlNormal" />
</item>
</selector>
diff --git a/core/res/res/drawable/scrubber_control_selector_quantum_dark.xml b/core/res/res/drawable/scrubber_control_selector_quantum_dark.xml
deleted file mode 100644
index 521bcca..0000000
--- a/core/res/res/drawable/scrubber_control_selector_quantum_dark.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_enabled="true" android:state_pressed="true">
- <bitmap android:src="@drawable/scrubber_control_on_pressed_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
- </item>
- <item>
- <bitmap android:src="@drawable/scrubber_control_on_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
- </item>
-</selector>
diff --git a/core/res/res/drawable/scrubber_progress_horizontal_quantum_light.xml b/core/res/res/drawable/scrubber_progress_horizontal_quantum.xml
similarity index 85%
rename from core/res/res/drawable/scrubber_progress_horizontal_quantum_light.xml
rename to core/res/res/drawable/scrubber_progress_horizontal_quantum.xml
index 053f542..7b124ac 100644
--- a/core/res/res/drawable/scrubber_progress_horizontal_quantum_light.xml
+++ b/core/res/res/drawable/scrubber_progress_horizontal_quantum.xml
@@ -17,10 +17,10 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item>
<bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:tint="?attr/colorControlNormal" />
</item>
</selector>
diff --git a/core/res/res/drawable/scrubber_progress_horizontal_quantum_dark.xml b/core/res/res/drawable/scrubber_progress_horizontal_quantum_dark.xml
deleted file mode 100644
index fa0d631..0000000
--- a/core/res/res/drawable/scrubber_progress_horizontal_quantum_dark.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true">
- <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
- </item>
- <item>
- <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
- </item>
-</selector>
diff --git a/core/res/res/drawable/spinner_background_quantum_dark.xml b/core/res/res/drawable/spinner_background_quantum.xml
similarity index 82%
rename from core/res/res/drawable/spinner_background_quantum_dark.xml
rename to core/res/res/drawable/spinner_background_quantum.xml
index d1e7407..727a78f 100644
--- a/core/res/res/drawable/spinner_background_quantum_dark.xml
+++ b/core/res/res/drawable/spinner_background_quantum.xml
@@ -18,14 +18,14 @@
android:autoMirrored="true">
<item android:state_checked="true">
<nine-patch android:src="@drawable/spinner_qntm_am_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item android:state_pressed="true">
<nine-patch android:src="@drawable/spinner_qntm_am_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item>
<nine-patch android:src="@drawable/spinner_qntm_am_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
</item>
</selector>
diff --git a/core/res/res/drawable/spinner_background_quantum_light.xml b/core/res/res/drawable/spinner_background_quantum_light.xml
deleted file mode 100644
index b01628d..0000000
--- a/core/res/res/drawable/spinner_background_quantum_light.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- android:autoMirrored="true">
- <item android:state_checked="true">
- <nine-patch android:src="@drawable/spinner_qntm_am_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item android:state_pressed="true">
- <nine-patch android:src="@drawable/spinner_qntm_am_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item>
- <nine-patch android:src="@drawable/spinner_qntm_am_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
- </item>
-</selector>
diff --git a/core/res/res/drawable/switch_inner_quantum_light.xml b/core/res/res/drawable/switch_inner_quantum.xml
similarity index 79%
rename from core/res/res/drawable/switch_inner_quantum_light.xml
rename to core/res/res/drawable/switch_inner_quantum.xml
index b5aa47b..915377e 100644
--- a/core/res/res/drawable/switch_inner_quantum_light.xml
+++ b/core/res/res/drawable/switch_inner_quantum.xml
@@ -17,18 +17,18 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:state_pressed="true">
<nine-patch android:src="@drawable/switch_on_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item android:state_checked="true">
<nine-patch android:src="@drawable/switch_on_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item android:state_pressed="true">
<nine-patch android:src="@drawable/switch_off_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item>
<nine-patch android:src="@drawable/switch_off_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
+ android:tint="?attr/colorControlNormal" />
</item>
</selector>
diff --git a/core/res/res/drawable/switch_inner_quantum_dark.xml b/core/res/res/drawable/switch_inner_quantum_dark.xml
deleted file mode 100644
index 927a55e..0000000
--- a/core/res/res/drawable/switch_inner_quantum_dark.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_checked="true" android:state_pressed="true">
- <nine-patch android:src="@drawable/switch_on_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
- </item>
- <item android:state_checked="true">
- <nine-patch android:src="@drawable/switch_on_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
- </item>
- <item android:state_pressed="true">
- <nine-patch android:src="@drawable/switch_off_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
- </item>
- <item>
- <nine-patch android:src="@drawable/switch_off_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
- </item>
-</selector>
diff --git a/core/res/res/drawable/switch_track_quantum_dark.xml b/core/res/res/drawable/switch_track_quantum.xml
similarity index 85%
rename from core/res/res/drawable/switch_track_quantum_dark.xml
rename to core/res/res/drawable/switch_track_quantum.xml
index c018bd2..8c4e6b71 100644
--- a/core/res/res/drawable/switch_track_quantum_dark.xml
+++ b/core/res/res/drawable/switch_track_quantum.xml
@@ -17,10 +17,10 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<nine-patch android:src="@drawable/switch_track_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item>
<nine-patch android:src="@drawable/switch_track_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
</item>
</selector>
diff --git a/core/res/res/drawable/switch_track_quantum_light.xml b/core/res/res/drawable/switch_track_quantum_light.xml
deleted file mode 100644
index ab87a57..0000000
--- a/core/res/res/drawable/switch_track_quantum_light.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_checked="true">
- <nine-patch android:src="@drawable/switch_track_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item>
- <nine-patch android:src="@drawable/switch_track_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
- </item>
-</selector>
diff --git a/core/res/res/drawable/tab_indicator_quantum_dark.xml b/core/res/res/drawable/tab_indicator_quantum.xml
similarity index 76%
rename from core/res/res/drawable/tab_indicator_quantum_dark.xml
rename to core/res/res/drawable/tab_indicator_quantum.xml
index 9b57c33..6fabe23 100644
--- a/core/res/res/drawable/tab_indicator_quantum_dark.xml
+++ b/core/res/res/drawable/tab_indicator_quantum.xml
@@ -17,27 +17,27 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:state_pressed="true">
<nine-patch android:src="@drawable/tab_indicator_selected_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item android:state_selected="true" android:state_focused="true">
<nine-patch android:src="@drawable/tab_indicator_selected_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item android:state_selected="true">
<nine-patch android:src="@drawable/tab_indicator_selected_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
</item>
<item android:state_pressed="true">
<nine-patch android:src="@drawable/tab_indicator_normal_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item android:state_focused="true">
<nine-patch android:src="@drawable/tab_indicator_normal_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
+ android:tint="?attr/colorControlActivated" />
</item>
<item>
<nine-patch android:src="@drawable/tab_indicator_normal_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_dark" />
+ android:tint="?attr/colorControlNormal" />
</item>
</selector>
diff --git a/core/res/res/drawable/tab_indicator_quantum_light.xml b/core/res/res/drawable/tab_indicator_quantum_light.xml
deleted file mode 100644
index 371322a..0000000
--- a/core/res/res/drawable/tab_indicator_quantum_light.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_selected="true" android:state_pressed="true">
- <nine-patch android:src="@drawable/tab_indicator_selected_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item android:state_selected="true" android:state_focused="true">
- <nine-patch android:src="@drawable/tab_indicator_selected_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item android:state_selected="true">
- <nine-patch android:src="@drawable/tab_indicator_selected_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
- </item>
-
- <item android:state_pressed="true">
- <nine-patch android:src="@drawable/tab_indicator_normal_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item android:state_focused="true">
- <nine-patch android:src="@drawable/tab_indicator_normal_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
- </item>
- <item>
- <nine-patch android:src="@drawable/tab_indicator_normal_qntm_alpha"
- android:tint="@color/control_normal_foreground_quantum_light" />
- </item>
-</selector>
diff --git a/core/res/res/drawable/text_cursor_quantum_light.xml b/core/res/res/drawable/text_cursor_quantum.xml
similarity index 91%
rename from core/res/res/drawable/text_cursor_quantum_light.xml
rename to core/res/res/drawable/text_cursor_quantum.xml
index 0ec7f01..23d4ae0 100644
--- a/core/res/res/drawable/text_cursor_quantum_light.xml
+++ b/core/res/res/drawable/text_cursor_quantum.xml
@@ -16,4 +16,4 @@
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/text_cursor_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_light" />
+ android:tint="?attr/colorControlActivated" />
diff --git a/core/res/res/drawable/text_cursor_quantum_dark.xml b/core/res/res/drawable/text_cursor_quantum_dark.xml
deleted file mode 100644
index bd0d66f..0000000
--- a/core/res/res/drawable/text_cursor_quantum_dark.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/text_cursor_qntm_alpha"
- android:tint="@color/control_activated_foreground_quantum_dark" />
diff --git a/core/res/res/layout/alert_dialog_progress_quantum.xml b/core/res/res/layout/alert_dialog_progress_quantum.xml
new file mode 100644
index 0000000..b9d0814
--- /dev/null
+++ b/core/res/res/layout/alert_dialog_progress_quantum.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent">
+ <ProgressBar android:id="@+id/progress"
+ style="?android:attr/progressBarStyleHorizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dip"
+ android:layout_marginBottom="1dip"
+ android:layout_marginStart="16dip"
+ android:layout_marginEnd="16dip"
+ android:layout_centerHorizontal="true" />
+ <TextView
+ android:id="@+id/progress_percent"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingBottom="16dip"
+ android:layout_marginStart="16dip"
+ android:layout_marginEnd="16dip"
+ android:layout_alignParentStart="true"
+ android:layout_below="@id/progress" />
+ <TextView
+ android:id="@+id/progress_number"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingBottom="16dip"
+ android:layout_marginStart="16dip"
+ android:layout_marginEnd="16dip"
+ android:layout_alignParentEnd="true"
+ android:layout_below="@id/progress" />
+</RelativeLayout>
diff --git a/core/res/res/layout/alert_dialog_quantum.xml b/core/res/res/layout/alert_dialog_quantum.xml
new file mode 100644
index 0000000..59dba08
--- /dev/null
+++ b/core/res/res/layout/alert_dialog_quantum.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/parentPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <LinearLayout android:id="@+id/topPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <LinearLayout android:id="@+id/title_template"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center_vertical|start"
+ android:paddingStart="16dip"
+ android:paddingEnd="16dip"
+ android:paddingTop="16dip">
+ <ImageView android:id="@+id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingEnd="8dip"
+ android:src="@null" />
+ <TextView android:id="@+id/alertTitle"
+ style="?android:attr/windowTitleStyle"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAlignment="viewStart" />
+ </LinearLayout>
+ <!-- If the client uses a customTitle, it will be added here. -->
+ </LinearLayout>
+
+ <LinearLayout android:id="@+id/contentPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:minHeight="64dp">
+ <ScrollView android:id="@+id/scrollView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipToPadding="false">
+ <TextView android:id="@+id/message"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="16dip"
+ android:paddingEnd="16dip"
+ android:paddingTop="16dip" />
+ </ScrollView>
+ </LinearLayout>
+
+ <FrameLayout android:id="@+id/customPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:minHeight="64dp">
+ <FrameLayout android:id="@+android:id/custom"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </FrameLayout>
+
+ <LinearLayout android:id="@+id/buttonPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/alert_dialog_button_bar_height"
+ android:orientation="vertical"
+ android:padding="16dip">
+ <LinearLayout
+ style="?android:attr/buttonBarStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layoutDirection="locale"
+ android:measureWithLargestChild="true">
+ <Button android:id="@+id/button3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start"
+ android:layout_marginRight="8dip"
+ android:maxLines="2"
+ android:minHeight="@dimen/alert_dialog_button_bar_height"
+ style="?android:attr/buttonBarButtonStyle" />
+ <View android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:visibility="invisible" />
+ <Button android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="end"
+ android:layout_marginRight="8dip"
+ android:maxLines="2"
+ android:minHeight="@dimen/alert_dialog_button_bar_height"
+ style="?android:attr/buttonBarButtonStyle" />
+ <Button android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="end"
+ android:maxLines="2"
+ android:minHeight="@dimen/alert_dialog_button_bar_height"
+ style="?android:attr/buttonBarButtonStyle" />
+ </LinearLayout>
+ </LinearLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/dialog_custom_title_quantum.xml b/core/res/res/layout/dialog_custom_title_quantum.xml
new file mode 100644
index 0000000..f8a2bf7
--- /dev/null
+++ b/core/res/res/layout/dialog_custom_title_quantum.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<!--
+This is a custom layout for a dialog.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:fitsSystemWindows="true">
+ <FrameLayout android:id="@android:id/title_container"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/alert_dialog_title_height"
+ android:layout_weight="0"
+ android:gravity="center_vertical|start"
+ style="?android:attr/windowTitleBackgroundStyle">
+ </FrameLayout>
+ <View android:id="@+id/titleDivider"
+ android:layout_width="match_parent"
+ android:layout_height="2dip"
+ android:background="@android:color/holo_blue_light" />
+ <FrameLayout
+ android:layout_width="match_parent" android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:foreground="?android:attr/windowContentOverlay">
+ <FrameLayout android:id="@android:id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+ </FrameLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/dialog_title_icons_quantum.xml b/core/res/res/layout/dialog_title_icons_quantum.xml
new file mode 100644
index 0000000..e3d771c
--- /dev/null
+++ b/core/res/res/layout/dialog_title_icons_quantum.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+
+<!--
+This is an optimized layout for a screen, with the minimum set of features
+enabled.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:fitsSystemWindows="true">
+
+ <LinearLayout android:id="@+id/title_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:minHeight="@android:dimen/alert_dialog_title_height"
+ android:paddingStart="16dip"
+ android:paddingEnd="16dip">
+ <ImageView android:id="@+id/left_icon"
+ android:layout_width="32dip"
+ android:layout_height="32dip"
+ android:scaleType="fitCenter"
+ android:layout_marginEnd="8dip" />
+ <TextView android:id="@android:id/title"
+ style="?android:attr/windowTitleStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="0" />
+ <ImageView android:id="@+id/right_icon"
+ android:layout_width="32dip"
+ android:layout_height="32dip"
+ android:scaleType="fitCenter"
+ android:layout_marginStart="8dip" />
+ </LinearLayout>
+
+ <View android:id="@+id/titleDivider"
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:background="@android:color/holo_blue_light" />
+
+ <FrameLayout
+ android:layout_width="match_parent" android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:foreground="?android:attr/windowContentOverlay">
+ <FrameLayout android:id="@android:id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+ </FrameLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/dialog_title_quantum.xml b/core/res/res/layout/dialog_title_quantum.xml
new file mode 100644
index 0000000..0a692ee
--- /dev/null
+++ b/core/res/res/layout/dialog_title_quantum.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, 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.
+*/
+
+This is an optimized layout for a screen, with the minimum set of features
+enabled.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:fitsSystemWindows="true">
+ <TextView android:id="@android:id/title" style="?android:attr/windowTitleStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="@android:dimen/alert_dialog_title_height"
+ android:paddingStart="16dip"
+ android:paddingEnd="16dip"
+ android:gravity="center_vertical|start" />
+ <View android:id="@+id/titleDivider"
+ android:layout_width="match_parent"
+ android:layout_height="2dip"
+ android:background="@android:color/holo_blue_light" />
+ <FrameLayout
+ android:layout_width="match_parent" android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:foreground="?android:attr/windowContentOverlay">
+ <FrameLayout android:id="@android:id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+ </FrameLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/notification_quantum_action.xml b/core/res/res/layout/notification_quantum_action.xml
index 775182f..0986343 100644
--- a/core/res/res/layout/notification_quantum_action.xml
+++ b/core/res/res/layout/notification_quantum_action.xml
@@ -16,7 +16,7 @@
-->
<Button xmlns:android="http://schemas.android.com/apk/res/android"
- style="?android:attr/borderlessButtonStyle"
+ style="@android:style/Widget.Quantum.Light.Button.Borderless.Small"
android:id="@+id/action0"
android:layout_width="0dp"
android:layout_height="48dp"
diff --git a/core/res/res/layout/notification_quantum_action_list.xml b/core/res/res/layout/notification_quantum_action_list.xml
index a8aef97..ec4919b 100644
--- a/core/res/res/layout/notification_quantum_action_list.xml
+++ b/core/res/res/layout/notification_quantum_action_list.xml
@@ -23,7 +23,7 @@
android:visibility="gone"
android:layout_marginBottom="8dp"
android:showDividers="middle"
- android:divider="?android:attr/listDivider"
+ android:divider="@drawable/list_divider_holo_light"
android:dividerPadding="12dp"
>
<!-- actions will be added here -->
diff --git a/core/res/res/layout/notification_quantum_action_tombstone.xml b/core/res/res/layout/notification_quantum_action_tombstone.xml
index 9104991..51e4205 100644
--- a/core/res/res/layout/notification_quantum_action_tombstone.xml
+++ b/core/res/res/layout/notification_quantum_action_tombstone.xml
@@ -16,7 +16,7 @@
-->
<Button xmlns:android="http://schemas.android.com/apk/res/android"
- style="?android:attr/borderlessButtonStyle"
+ style="@android:style/Widget.Quantum.Light.Button.Borderless.Small"
android:id="@+id/action0"
android:layout_width="0dp"
android:layout_height="48dp"
diff --git a/core/res/res/layout/notification_template_quantum_base.xml b/core/res/res/layout/notification_template_quantum_base.xml
index 3e97b2a..8863cfa 100644
--- a/core/res/res/layout/notification_template_quantum_base.xml
+++ b/core/res/res/layout/notification_template_quantum_base.xml
@@ -92,7 +92,7 @@
android:layout_height="12dp"
android:layout_marginStart="8dp"
android:visibility="gone"
- style="?android:attr/progressBarStyleHorizontal"
+ style="@style/Widget.Quantum.Light.ProgressBar.Horizontal"
/>
<LinearLayout
android:id="@+id/line3"
diff --git a/core/res/res/layout/notification_template_quantum_big_base.xml b/core/res/res/layout/notification_template_quantum_big_base.xml
index d860045..63935bb 100644
--- a/core/res/res/layout/notification_template_quantum_big_base.xml
+++ b/core/res/res/layout/notification_template_quantum_big_base.xml
@@ -148,7 +148,7 @@
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:visibility="gone"
- style="?android:attr/progressBarStyleHorizontal"
+ style="@style/Widget.Quantum.Light.ProgressBar.Horizontal"
/>
</LinearLayout>
<ImageView
@@ -156,7 +156,7 @@
android:layout_height="1dp"
android:id="@+id/action_divider"
android:visibility="gone"
- android:background="?android:attr/dividerHorizontal" />
+ android:background="@drawable/list_divider_holo_light" />
<include
layout="@layout/notification_quantum_action_list"
android:layout_width="match_parent"
diff --git a/core/res/res/layout/notification_template_quantum_big_text.xml b/core/res/res/layout/notification_template_quantum_big_text.xml
index 585be80..516b0c4 100644
--- a/core/res/res/layout/notification_template_quantum_big_text.xml
+++ b/core/res/res/layout/notification_template_quantum_big_text.xml
@@ -101,7 +101,7 @@
android:layout_marginEnd="8dp"
android:visibility="gone"
android:layout_weight="0"
- style="?android:attr/progressBarStyleHorizontal"
+ style="@style/Widget.Quantum.Light.ProgressBar.Horizontal"
/>
<TextView android:id="@+id/big_text"
android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
@@ -121,7 +121,7 @@
android:layout_height="1dip"
android:id="@+id/action_divider"
android:visibility="gone"
- android:background="?android:attr/dividerHorizontal" />
+ android:background="@drawable/list_divider_holo_light" />
<include
layout="@layout/notification_quantum_action_list"
android:layout_width="match_parent"
@@ -135,7 +135,7 @@
android:id="@+id/overflow_divider"
android:layout_marginBottom="8dp"
android:visibility="visible"
- android:background="?android:attr/dividerHorizontal" />
+ android:background="@drawable/list_divider_holo_light" />
<LinearLayout
android:id="@+id/line3"
android:layout_width="match_parent"
diff --git a/core/res/res/layout/notification_template_quantum_inbox.xml b/core/res/res/layout/notification_template_quantum_inbox.xml
index 31ed508..c6192be 100644
--- a/core/res/res/layout/notification_template_quantum_inbox.xml
+++ b/core/res/res/layout/notification_template_quantum_inbox.xml
@@ -103,7 +103,7 @@
android:layout_marginEnd="8dp"
android:visibility="gone"
android:layout_weight="0"
- style="?android:attr/progressBarStyleHorizontal"
+ style="@style/Widget.Quantum.Light.ProgressBar.Horizontal"
/>
<TextView android:id="@+id/inbox_text0"
android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
@@ -206,7 +206,7 @@
android:layout_height="1dip"
android:id="@+id/action_divider"
android:visibility="gone"
- android:background="?android:attr/dividerHorizontal" />
+ android:background="@drawable/list_divider_holo_light" />
<include
layout="@layout/notification_quantum_action_list"
android:layout_width="match_parent"
@@ -218,7 +218,7 @@
android:layout_height="1dip"
android:id="@+id/overflow_divider"
android:visibility="visible"
- android:background="?android:attr/dividerHorizontal" />
+ android:background="@drawable/list_divider_holo_light" />
<LinearLayout
android:id="@+id/line3"
android:layout_width="match_parent"
diff --git a/core/res/res/layout/progress_dialog_quantum.xml b/core/res/res/layout/progress_dialog_quantum.xml
new file mode 100644
index 0000000..84d06b5
--- /dev/null
+++ b/core/res/res/layout/progress_dialog_quantum.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <LinearLayout android:id="@+id/body"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:baselineAligned="false"
+ android:padding="16dip">
+
+ <ProgressBar android:id="@android:id/progress"
+ style="?android:attr/progressBarStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:max="10000"
+ android:layout_marginEnd="16dip" />
+
+ <TextView android:id="@+id/message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical" />
+ </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index 3265736..b1afec1 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -24,7 +24,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:splitMotionEvents="false"
- android:theme="?attr/actionBarTheme">
+ android:theme="?attr/actionBarWidgetTheme">
<FrameLayout android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="match_parent" />
diff --git a/core/res/res/layout/select_dialog_item_quantum.xml b/core/res/res/layout/select_dialog_item_quantum.xml
new file mode 100644
index 0000000..59b432e
--- /dev/null
+++ b/core/res/res/layout/select_dialog_item_quantum.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!--
+ This layout file is used by the AlertDialog when displaying a list of items.
+ This layout file is inflated and used as the TextView to display individual
+ items.
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:textAppearance="?android:attr/textAppearanceListItemSmall"
+ android:textColor="?android:attr/textColorAlertDialogListItem"
+ android:gravity="center_vertical"
+ android:paddingStart="16dip"
+ android:paddingEnd="16dip"
+ android:ellipsize="marquee" />
diff --git a/core/res/res/layout/select_dialog_multichoice_quantum.xml b/core/res/res/layout/select_dialog_multichoice_quantum.xml
new file mode 100644
index 0000000..8b4c59d
--- /dev/null
+++ b/core/res/res/layout/select_dialog_multichoice_quantum.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorAlertDialogListItem"
+ android:gravity="center_vertical"
+ android:paddingStart="16dip"
+ android:paddingEnd="16dip"
+ android:checkMark="?android:attr/listChoiceIndicatorMultiple"
+ android:ellipsize="marquee" />
diff --git a/core/res/res/layout/select_dialog_quantum.xml b/core/res/res/layout/select_dialog_quantum.xml
new file mode 100644
index 0000000..ee04039
--- /dev/null
+++ b/core/res/res/layout/select_dialog_quantum.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!--
+ This layout file is used by the AlertDialog when displaying a list of items.
+ This layout file is inflated and used as the ListView to display the items.
+ Assign an ID so its state will be saved/restored.
+-->
+<view class="com.android.internal.app.AlertController$RecycleListView"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+android:id/select_dialog_listview"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:cacheColorHint="@null"
+ android:divider="?android:attr/listDividerAlertDialog"
+ android:scrollbars="vertical"
+ android:overScrollMode="ifContentScrolls"
+ android:textAlignment="viewStart" />
diff --git a/core/res/res/layout/select_dialog_singlechoice_quantum.xml b/core/res/res/layout/select_dialog_singlechoice_quantum.xml
new file mode 100644
index 0000000..27a6648
--- /dev/null
+++ b/core/res/res/layout/select_dialog_singlechoice_quantum.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorAlertDialogListItem"
+ android:gravity="center_vertical"
+ android:paddingStart="16dip"
+ android:paddingEnd="16dip"
+ android:checkMark="?android:attr/listChoiceIndicatorSingle"
+ android:ellipsize="marquee" />
diff --git a/core/res/res/layout/tab_indicator_quantum.xml b/core/res/res/layout/tab_indicator_quantum.xml
new file mode 100644
index 0000000..fcb2d5f
--- /dev/null
+++ b/core/res/res/layout/tab_indicator_quantum.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="?android:attr/actionBarSize"
+ android:orientation="horizontal"
+ style="@android:style/Widget.Quantum.Tab">
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:visibility="gone" />
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ style="@android:style/Widget.Quantum.TabText" />
+
+</LinearLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 5cb5709..f8d7fcc 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Laat die program toe om die inhoud van die aktiewe venster op te haal. Kwaadwillige programme kan die hele venster se inhoud ophaal, en al die teks ondersoek, behalwe wagwoorde."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"aktiveer toeganklikheid tydelik"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Laat \'n program toe om toeganklikheid tydelik op die toestel te aktiveer. Kwaadwillige programme kan sonder die toestemming van die gebruiker toeganklikheid verkry."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"haal vensterinligting op"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Laat \'n program toe om inligting oor vensters vanaf die vensterbestuurder op te haal. Kwaadwillige programme kan moontlik inligting ophaal wat vir interne stelselgebruik bedoel is."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filter gebeure"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Laat \'n program toe om \'n invoerfilter te registreer wat die stroom van alle gebruikergebeure filter voordat dit versend word. Kwaadwillige programme kan moontlik die stelsel-UI beheer sonder gebruikers se tussentrede."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"vergroot skerm"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Laat \'n program toe om die inhoud van \'n skerm te vergroot. Kwaadwillige programme kan die skerminhoud so omskep dat die toestel onbruikbaar word."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"gedeeltelike afskakeling"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Plaas die aktiwiteitbestuurder in \'n afsluitingstatus. Doen nie \'n volledige afsluiting nie."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"verhoed program-oorskakelings"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 5509121..0e5a0e7 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"የነቃ መስኮት ይዘትን ለመበርበር ለመተግበሪያው ይፈቅዳሉ፡፡ ጠቅላላውን የመስኮት ይዘት ለመበርበር እና ከይለፍ ቃል በስተቀር ሁሉንም ጽሑፉን ለማየት ጎጂ መተግበሪያዎች ይችላሉ፡፡"</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ተደራሽነት በጊዜያዊነት ያነቃል"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"አንድ መተግበሪያ በጊዜያዊነት በመሣሪያው ላይ ተደራሽነትን እንዲያነቃ ያስችለዋል። ተንኮል-አዘል መተግበሪያዎች ያለተጠቃሚው ፍቃድ ተደራሽነትን ሊያነቁ ይችላሉ።"</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"የመስኮት መረጃን አምጣ"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"አንድ መተግበሪያ ከመስኮት አቀናባሪው ሆኖ ስለመስኮቱ መረጃ እንዲያመጣ ያስችለዋል። ተንኮል-አዘል መተግበሪያዎች ለውስጣዊ ስርዓት ጥቅም የታሰበ መረጃን ሊወስዱ ይችላሉ።"</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"ክስተቶችን አጣራ"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"አንድ መተግበሪያ የሁሉንም ተጠቃሚዎች ክስተቶች ከመላካቸው በፊት እነሱን የሚያጣራ የግቤት ማጣሪያ እንዲመዘግብ ያስችለዋል። ተንኮል-አዘል መተግበሪያዎች ተጠቃሚው ጣልቃ ሳይገባ የስርዓቱን በይነገጽ ሊቆጣጠሩት ይችላሉ።"</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"ማሳያን አጉላ"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"አንድ መተግበሪያ የአንድ ማሳያ ይዘት እንዲያጎላ ይፈቅድለታል። ተንኮል-አዘል መተግበሪያዎች መሣሪያውን ከጥቅም ውጪ በሚያደርገው ሁኔታ የማሳያ ይዘቱ ሊለውጡት ይችላሉ።"</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"ከፊል ዝጋ"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"የእንቅስቃሴውን አደራጅ ወደ ዝጋ ሁነታ አስቀምጥ።ሙሉ ለሙሉ ዝጋ አያከናውንም።"</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"የትግበራ መቀያየርን ተከላከል"</string>
@@ -992,7 +988,7 @@
<string name="search_go" msgid="8298016669822141719">"ፍለጋ"</string>
<string name="searchview_description_search" msgid="6749826639098512120">"ፍለጋ"</string>
<string name="searchview_description_query" msgid="5911778593125355124">"ጥያቄ ፍለጋ"</string>
- <string name="searchview_description_clear" msgid="1330281990951833033">"ጥያቄ አጥራ"</string>
+ <string name="searchview_description_clear" msgid="1330281990951833033">"ጥያቄ አጽዳ"</string>
<string name="searchview_description_submit" msgid="2688450133297983542">"ጥያቄ አስረክብ"</string>
<string name="searchview_description_voice" msgid="2453203695674994440">"የድምፅ ፍለጋ"</string>
<string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"በመንካት አስስ ይንቃ?"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index d17b1d1..c808135 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"للسماح للتطبيق باسترداد محتوى النافذة النشطة. يمكن للبرامج الضارة استرداد محتوى النافذة بالكامل وفحص جميع النصوص الموجودة بها باستثناء كلمات المرور."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"تمكين إمكانية الدخول مؤقتًا"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"يتيح لتطبيق تمكين إمكانية الدخول مؤقتًا بالجهاز. قد تتيح التطبيقات الضارة تمكين إمكانية الدخول بدون موافقة المستخدم."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"استرداد معلومات النوافذ"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"للسماح لأحد التطبيقات باستعادة معلومات حول النوافذ من مدير النوافذ. يمكن أن تستعيد التطبيقات الضارة معلومات الغرض منها استخدام النظام الداخلي."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"تصفية الأحداث"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"للسماح لأحد التطبيقات بتسجيل فلتر إدخال يعمل على تصفية مجموعة البث من جميع أحداث المستخدمين قبل إرسالها. يمكن أن يتحكم برنامج ضار في واجهة المستخدم النظام دون تدخل المستخدم."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"تكبير الشاشة"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"للسماح للتطبيق بتكبير محتوى شاشة. قد تؤدي التطبيقات الضارة إلى نقل محتوى الشاشة بطريقة تعرض الجهاز في وضع غير قابل للاستخدام."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"إيقاف تشغيل جزئي"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"لوضع مدير الأنشطة في حالة إيقاف التشغيل. لا يتم تنفيذ إيقاف تشغيل كامل."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"منع التبديل بين التطبيقات"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 691aff26..015bf10 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Разрешава на приложението да извлича съдържанието от активния прозорец. Злонамерените приложения могат да извлекат цялото му съдържание и да проследят целия текст в него освен паролите."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"временно активиране на достъпността"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Разрешава на приложението временно да активира достъпността на устройството. Злонамерените приложения може да я активират без съгласието на потребителя."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"извличане на информация за прозорците"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Разрешава на приложението да извлича информация за прозорците от съответния мениджър. Злонамерените приложения може да извличат данни, които са предназначени за вътрешно използване от системата."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"филтриране на събитията"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Разрешава на приложението да регистрира входящ филтър, който филтрира потока на всички потребителски събития преди изпращането им. Злонамерено приложение може да контролира системния потребителски интерфейс без намесата на потребителя."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"промяна на мащаба на дисплея"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Разрешава на приложението да променя мащаба на съдържанието на дисплей. Злонамерените приложения може да преобразят съдържанието на дисплея по начин, който изобразява устройството като неизползваемо."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"частично изключване"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Изключва диспечера на дейностите. Не извършва пълно изключване."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"предотвратяване на превключването между приложения"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 0330b7b..94f4b4f 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -136,7 +136,7 @@
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Massa supressions de <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"L\'emmagatzematge de la tauleta és ple. Suprimeix uns quants fitxers per alliberar espai."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"L\'emmagatzematge del telèfon és ple. Suprimeix uns quants fitxers per alliberar espai."</string>
- <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Pot ser que la xarxa se supervisi."</string>
+ <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"És possible que la xarxa estigui supervisada"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Per un tercer desconegut"</string>
<string name="ssl_ca_cert_noti_managed" msgid="4030263497686867141">"Per <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string>
<string name="me" msgid="6545696007631404292">"Mi"</string>
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permet que l\'aplicació recuperi el contingut de la finestra activa. Les aplicacions malicioses poden recuperar el contingut de tota la finestra i examinar-ne tot el text, excepte les contrasenyes."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"activació temporal de l\'accessibilitat"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permet que una aplicació activi temporalment l\'accessibilitat al dispositiu. És possible que les aplicacions malicioses activin l\'accessibilitat sense el consentiment de l\'usuari."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recupera informació de les finestres"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permet que una aplicació recuperi informació sobre les finestres del gestor de finestres. Aplicacions malicioses podrien recuperar informació dirigida a la utilització per part del sistema intern."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtra els esdeveniments"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Permet que una aplicació registri un filtre d\'entrada per a l\'emissió de tots els esdeveniments d\'usuari abans no s\'enviïn. Aplicacions malicioses podrien controlar la IU del sistema sense la intervenció de l\'usuari."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"augment de la pantalla"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Permet a una aplicació augmentar el contingut d\'una pantalla. Les aplicacions malicioses poden transformar el contingut de la pantalla de manera que el dispositiu no es pugui fer servir."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"apagar parcialment"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Posa el gestor d\'activitats en estat d\'apagada. No fa una apagada completa."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir els canvis d\'aplicació"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 37e228c..b3f482a 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Umožňuje aplikaci načíst obsah aktivního okna. Škodlivé aplikace mohou načíst obsah celého okna a prozkoumat všechen text kromě hesel."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"dočasná aktivace usnadnění přístupu"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Umožňuje aplikaci dočasně aktivovat usnadnění přístupu v zařízení. Škodlivé aplikace mohou usnadnění přístupu aktivovat bez souhlasu uživatele."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"načítání informací o oknech"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Umožňuje aplikaci načíst informace o oknech ze správce oken. Škodlivé aplikace mnohou načíst informace, které slouží k internímu systémovému využití."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtrování událostí"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Umožní aplikaci registrovat vstupní filtr, který filtruje stream všech uživatelských přenosů před jejich odvysíláním. Škodlivé aplikace mohou používat uživatelské rozhraní systému bez zásahu uživatele."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"zvětšit zobrazení"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Povoluje aplikaci zvětšit obsah displeje. Škodlivé aplikace mohou změnit zobrazení obsahu způsobem, který učiní zařízení nepoužitelným."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"částečné vypnutí"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Uvede správce činností do vypnutého stavu. Nedojde však k úplnému vypnutí."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zabránění přepínání aplikací"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 5acf558..a8cf79c 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -46,7 +46,7 @@
<string name="badPin" msgid="9015277645546710014">"Den gamle pinkode, som du har indtastet, er ikke korrekt."</string>
<string name="badPuk" msgid="5487257647081132201">"Den indtastede PUK-kode er forkert."</string>
<string name="mismatchPin" msgid="609379054496863419">"De indtastede pinkoder er ikke ens"</string>
- <string name="invalidPin" msgid="3850018445187475377">"Indtast en PIN-kode på mellem 4 og 8 tal."</string>
+ <string name="invalidPin" msgid="3850018445187475377">"Indtast en pinkode på mellem 4 og 8 tal."</string>
<string name="invalidPuk" msgid="8761456210898036513">"Angiv en PUK-kode på 8 eller flere cifre."</string>
<string name="needPuk" msgid="919668385956251611">"Dit SIM-kort er låst med PUK-koden. Indtast PUK-koden for at låse den op."</string>
<string name="needPuk2" msgid="4526033371987193070">"Indtast PUK2-koden for at låse op for SIM-kortet."</string>
@@ -63,12 +63,12 @@
<string name="CwMmi" msgid="9129678056795016867">"Ventende opkald"</string>
<string name="BaMmi" msgid="455193067926770581">"Opkaldsspærring"</string>
<string name="PwdMmi" msgid="7043715687905254199">"Ændring af adgangskode"</string>
- <string name="PinMmi" msgid="3113117780361190304">"ændring af PIN-kode"</string>
+ <string name="PinMmi" msgid="3113117780361190304">"ændring af pinkode"</string>
<string name="CnipMmi" msgid="3110534680557857162">"Opkaldsnummeret er til stede"</string>
<string name="CnirMmi" msgid="3062102121430548731">"Opkaldsnummeret er begrænset"</string>
<string name="ThreeWCMmi" msgid="9051047170321190368">"Trevejsopkald"</string>
<string name="RuacMmi" msgid="7827887459138308886">"Afvisning af uønskede, irriterende opkald"</string>
- <string name="CndMmi" msgid="3116446237081575808">"Levering af opkaldsnummer"</string>
+ <string name="CndMmi" msgid="3116446237081575808">"Levering af nummervisning"</string>
<string name="DndMmi" msgid="1265478932418334331">"Forstyr ikke"</string>
<string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Standarder for opkalds-id til begrænset. Næste opkald: Begrænset"</string>
<string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Standarder for opkalds-id til begrænset. Næste opkald: Ikke begrænset"</string>
@@ -241,7 +241,7 @@
<string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"undersøge indholdet i et vindue, du interagerer med."</string>
<string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"aktivere Udforsk ved berøring"</string>
<string name="capability_desc_canRequestTouchExploration" msgid="5800552516779249356">"De emner, der trykkes på, læses højt, og skærmen kan udforskes ved hjælp af bevægelser."</string>
- <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"aktivere forbedret webhjælpefunktioner"</string>
+ <string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"aktivere forbedrede webhjælpefunktioner"</string>
<string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"Der installeres muligvis scripts for at gøre appindhold mere tilgængeligt."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"observere tekst, du skriver"</string>
<string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Dette omfatter personlige data såsom kreditkortnumre og adgangskoder."</string>
@@ -263,8 +263,8 @@
<string name="permdesc_receiveMms" msgid="533019437263212260">"Tillader, at appen kan modtage og behandle mms-beskeder. Det betyder, at appen kan overvåge eller slette de beskeder, der sendes til din enhed, uden at vise dem til dig."</string>
<string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"modtage nødudsendelser"</string>
<string name="permdesc_receiveEmergencyBroadcast" msgid="848524070262431974">"Tillader, at appen kan modtage og behandle nødtransmissioner. Denne tilladelse er kun tilgængelig for systemapps."</string>
- <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"læse mobiltransmissionsbeskeder"</string>
- <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Tillader, at appen læser mobiltransmissionsbeskeder, der modtages af din enhed. I nogle områder sendes mobiltransmissionsbeskeder for at advare om nødsituationer. Ondsindede apps kan forstyrre ydelsen eller driften af din enhed, når en mobiltransmission om en nødsituation modtages."</string>
+ <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"læse Cell Broadcast-beskeder"</string>
+ <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Tillader, at appen læser Cell Broadcast-beskeder, der modtages af din enhed. I nogle områder sendes der Cell Broadcast-beskeder for at advare om nødsituationer. Ondsindede apps kan forstyrre ydelsen eller driften af din enhed, når der modtages en Cell Broadcast-besked om en nødsituation."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"send sms-beskeder"</string>
<string name="permdesc_sendSms" msgid="7094729298204937667">"Tillader, at appen kan sende sms-beskeder. Dette kan resultere i uventede opkrævninger. Skadelige apps kan koste dig penge ved at sende beskeder uden din bekræftelse."</string>
<string name="permlab_sendRespondViaMessageRequest" msgid="8713889105305943200">"send hændelser, hvor der skal svares pr. besked"</string>
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Tillader, at appen kan hente indholdet i det aktive vindue. Ondsindede apps kan hente al indholdet i vinduet og undersøge al dens tekst med undtagelse af adgangskoder."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"aktivere hjælpefunktioner midlertidigt"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Tillader, at en app midlertidigt kan aktivere hjælpefunktioner på enheden. Skadelige apps kan muligvis aktivere hjælpefunktioner uden brugerens samtykke."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"hent oplysninger om vinduer"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Tillader, at en applikation henter oplysninger om vinduerne i vinduesadministratoren. Skadelige apps kan muligvis hente oplysninger, der er beregnet til intern systembrug."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtrer begivenheder"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Tillader, at en applikation registrerer et inputfilter, som filtrerer alle brugeres strøm, før disse afsendes. Skadelige apps kan muligvis kontrollere systemets grænseflade uden brugerens deltagelse."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"forstør skærmen"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Tillader, at applikationer kan forstørre indholdet på en skærm. Skadelige apps kan omdanne skærmindholdet, så enheden bliver ubrugelig."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"delvis lukning"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Sætter aktivitetsadministratoren i lukningstilstand. Lukker ikke helt ned."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"undgå programskift"</string>
@@ -380,7 +376,7 @@
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Tillader, at ejeren kan binde en teksttjenestes grænseflade (f. eks. SpellCheckerService) på øverste niveau. Dette bør aldrig være nødvendigt til normale apps."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"bind til en VPN-tjeneste"</string>
<string name="permdesc_bindVpnService" msgid="2067845564581693905">"Tillader, at brugeren forpligter sig til en VPN-tjenestes grænseflade på øverste niveau. Bør aldrig være nødvendigt i almindelige apps."</string>
- <string name="permlab_bindWallpaper" msgid="8716400279937856462">"forpligt til et tapet"</string>
+ <string name="permlab_bindWallpaper" msgid="8716400279937856462">"knyt til en baggrund"</string>
<string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Tillader, at indehaveren kan binde en baggrunds grænseflade på øverste niveau. Dette bør aldrig være nødvendigt for almindelige apps."</string>
<string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bind til en ekstern skærm"</string>
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Tillader, at brugeren kan foretage en binding til grænsefladens øverste niveau på en ekstern skærm. Bør aldrig være nødvendigt til almindelige apps."</string>
@@ -579,7 +575,7 @@
<string name="permlab_factoryTest" msgid="3715225492696416187">"kør i fabriksindstillet testtilstand"</string>
<string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Kør som en producenttest på lavt niveau, der giver fuld adgang til tabletens hardware. Kun tilgængeligt når en tablet kører i producenttesttilstand."</string>
<string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Kør som en producenttest på lavt niveau. Giver fuld adgang til telefonens hardware. Kun tilgængeligt når en telefon kører i producenttesttilstand."</string>
- <string name="permlab_setWallpaper" msgid="6627192333373465143">"angiv tapet"</string>
+ <string name="permlab_setWallpaper" msgid="6627192333373465143">"angive baggrund"</string>
<string name="permdesc_setWallpaper" msgid="7373447920977624745">"Tillader, at appen kan konfigurere systembaggrunden."</string>
<string name="permlab_setWallpaperHints" msgid="3278608165977736538">"ændre størrelsen på din baggrund"</string>
<string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"Tillader, at appen giver tips til systembaggrundens størrelse."</string>
@@ -1346,8 +1342,8 @@
<string name="input_method_binding_label" msgid="1283557179944992649">"Inputmetode"</string>
<string name="sync_binding_label" msgid="3687969138375092423">"Synkroniser"</string>
<string name="accessibility_binding_label" msgid="4148120742096474641">"Hjælpefunktioner"</string>
- <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapet"</string>
- <string name="chooser_wallpaper" msgid="7873476199295190279">"Skift tapet"</string>
+ <string name="wallpaper_binding_label" msgid="1240087844304687662">"Baggrund"</string>
+ <string name="chooser_wallpaper" msgid="7873476199295190279">"Skift baggrund"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"Underretningslytter"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN er aktiveret."</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveres af <xliff:g id="APP">%s</xliff:g>"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index f87865d..80a4ed27 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -145,7 +145,7 @@
<string name="silent_mode" msgid="7167703389802618663">"Lautlos-Modus"</string>
<string name="turn_on_radio" msgid="3912793092339962371">"Funk einschalten"</string>
<string name="turn_off_radio" msgid="8198784949987062346">"Funk ausschalten"</string>
- <string name="screen_lock" msgid="799094655496098153">"Display-Sperre"</string>
+ <string name="screen_lock" msgid="799094655496098153">"Displaysperre"</string>
<string name="power_off" msgid="4266614107412865048">"Ausschalten"</string>
<string name="silent_mode_silent" msgid="319298163018473078">"Klingelton aus"</string>
<string name="silent_mode_vibrate" msgid="7072043388581551395">"Klingeltonmodus \"Vibration\""</string>
@@ -160,7 +160,7 @@
<string name="no_recent_tasks" msgid="8794906658732193473">"Keine kürzlich geöffneten Apps"</string>
<string name="global_actions" product="tablet" msgid="408477140088053665">"Tablet-Optionen"</string>
<string name="global_actions" product="default" msgid="2406416831541615258">"Telefonoptionen"</string>
- <string name="global_action_lock" msgid="2844945191792119712">"Display-Sperre"</string>
+ <string name="global_action_lock" msgid="2844945191792119712">"Displaysperre"</string>
<string name="global_action_power_off" msgid="4471879440839879722">"Ausschalten"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Fehlerbericht"</string>
<string name="bugreport_title" msgid="2667494803742548533">"Fehlerbericht abrufen"</string>
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Ermöglicht der App, den Inhalt des aktiven Fensters abzurufen. Schädliche Apps können so den gesamten Fensterinhalt abrufen und mit Ausnahme von Passwörtern den gesamten Text auswerten."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Bedienungshilfen vorübergehend aktivieren"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Ermöglicht einer App, die Bedienungshilfen auf dem Gerät vorübergehend zu aktivieren. Schädliche Apps können Bedienungshilfen ohne die Zustimmung des Nutzers aktivieren."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"Fensterinformationen abrufen"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Ermöglicht einer App, Informationen über die Fenster vom Fenster-Manager abzurufen. Schädliche Apps können Informationen abrufen, die für die systeminterne Nutzung gedacht sind."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"Ereignisse filtern"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Ermöglicht einer App, einen Eingabefilter zu registrieren, der den Stream aller Nutzerereignisse vor ihrem Versand filtert. Eine schädliche App kann die System-UI ohne Eingriff des Nutzers kontrollieren."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"Anzeige vergrößern"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Erlaubt der App, den Inhalt einer Anzeige zu vergrößern. Schädliche Apps verändern eventuell die Ansicht, sodass Inhalte nicht richtig angezeigt werden."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"Partielles Herunterfahren"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Versetzt den Aktivitätsmanager in einen heruntergefahrenen Zustand. Führt kein vollständiges Herunterfahren aus."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"App-Wechsel verhindern"</string>
@@ -637,7 +633,7 @@
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Ermöglicht der App, die Bluetooth-Konfiguration des Telefons einzusehen und Verbindungen mit gekoppelten Geräten herzustellen und zu akzeptieren."</string>
<string name="permlab_nfc" msgid="4423351274757876953">"Nahfeldkommunikation steuern"</string>
<string name="permdesc_nfc" msgid="7120611819401789907">"Ermöglicht der App die Kommunikation mit Tags für die Nahfeldkommunikation, Karten und Readern"</string>
- <string name="permlab_disableKeyguard" msgid="3598496301486439258">"Display-Sperre deaktivieren"</string>
+ <string name="permlab_disableKeyguard" msgid="3598496301486439258">"Displaysperre deaktivieren"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Ermöglicht der App, die Tastensperre sowie den damit verbundenen Passwortschutz zu deaktivieren. Das Telefon deaktiviert die Tastensperre beispielsweise, wenn ein Anruf eingeht, und aktiviert sie wieder, nachdem das Gespräch beendet wurde."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"Synchronisierungseinstellungen lesen"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Ermöglicht der App, die Synchronisierungseinstellungen eines Kontos zu lesen. Beispielsweise kann damit festgestellt werden, ob Kontakte mit einem Konto synchronisiert werden."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index e144e9d..ddee3106 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Επιτρέπει στην εφαρμογή την ανάκτηση του περιεχομένου του ενεργού παραθύρου. Τυχόν κακόβουλες εφαρμογές ενδέχεται να ανακτήσουν ολόκληρο το περιεχόμενο του παραθύρου και να εξετάσουν ολόκληρο το κείμενό του εκτός από τους κωδικούς πρόσβασης."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"προσωρινή ενεργοποίηση προσβασιμότητας"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Επιτρέπει σε μια εφαρμογή να ενεργοποιήσει την προσβασιμότητα στη συσκευή. Οι κακόβουλες εφαρμογές ενδέχεται να ενεργοποιήσουν την προσβασιμότητα χωρίς τη συγκατάθεση των χρηστών."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"ανάκτηση πληροφοριών παραθύρων"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Επιτρέπει σε μια εφαρμογή να ανακτήσει πληροφορίες σχετικά με τα παράθυρα από το διαχειριστή παραθύρων. Οι κακόβουλες εφαρμογές ενδέχεται να ανακτήσουν πληροφορίες που προορίζονται για την εσωτερική χρήση του συστήματος."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"φιλτράρισμα συμβάντων"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Επιτρέπει σε μια εφαρμογή να καταγράφει ένα φίλτρο εισαγωγής, το οποίο φιλτράρει τη ροή όλων των συμβάντων χρήστη πριν την αποστολή τους. Μια κακόβουλη εφαρμογή μπορεί να ελέγξει τη διεπαφή του συστήματος χωρίς την παρέμβαση του χρήστη."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"μεγέθυνση οθόνης"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Επιτρέπει στην εφαρμογή να μεγεθύνει το περιεχόμενο της οθόνης. Οι κακόβουλες εφαρμογές ενδέχεται να τροποποιούν το περιεχόμενο της οθόνης με τέτοιο τρόπο ώστε η εφαρμογή να μην μπορεί να χρησιμοποιηθεί."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"μερικός τερματισμός λειτουργίας"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Θέτει το πρόγραμμα διαχείρισης δραστηριοτήτων σε κατάσταση τερματισμού λειτουργιών. Δεν εκτελεί πλήρη τερματισμό λειτουργιών."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"αποτροπή εναλλαγών εφαρμογών"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 19ea67b..1c815be 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Allows the app to retrieve the content of the active window. Malicious apps may retrieve the entire window content and examine all its text except passwords."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"temporary enable accessibility"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Allows an application to temporarily enable accessibility on the device. Malicious apps may enable accessibility without user consent."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"retrieve window info"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Allows an application to retrieve information about the windows from the window manager. Malicious apps may retrieve information that is intended for internal system usage."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filter events"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Allows an application to register an input filter which filters the stream of all user events before they are dispatched. Malicious app may control the system UI without user intervention."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"magnify display"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Allows an application to magnify the content of a display. Malicious apps may transform the display content in a way that renders the device unusable."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"partial shutdown"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Puts the activity manager into a shut-down state. Does not perform a complete shut down."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"prevent app switches"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 19ea67b..1c815be 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Allows the app to retrieve the content of the active window. Malicious apps may retrieve the entire window content and examine all its text except passwords."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"temporary enable accessibility"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Allows an application to temporarily enable accessibility on the device. Malicious apps may enable accessibility without user consent."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"retrieve window info"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Allows an application to retrieve information about the windows from the window manager. Malicious apps may retrieve information that is intended for internal system usage."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filter events"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Allows an application to register an input filter which filters the stream of all user events before they are dispatched. Malicious app may control the system UI without user intervention."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"magnify display"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Allows an application to magnify the content of a display. Malicious apps may transform the display content in a way that renders the device unusable."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"partial shutdown"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Puts the activity manager into a shut-down state. Does not perform a complete shut down."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"prevent app switches"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 2c9599c..16790eb 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que la aplicación recupere el contenido de la ventana activa. Las aplicaciones maliciosas pueden recuperar el contenido completo de la ventana y examinar todo el texto, excepto las contraseñas."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Activación temporal de la accesibilidad"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permite a una aplicación activar temporalmente la accesibilidad en el dispositivo. Las aplicaciones maliciosas pueden activar la accesibilidad sin el consentimiento del usuario."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recuperar información de ventanas"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permite que una aplicación recupere la información del administrador de ventanas relacionada con estas. Las aplicaciones maliciosas pueden recuperar información destinada al uso interno del sistema."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que una aplicación registre un filtro de entrada que filtre la transmisión de todos los eventos del usuario antes de ser enviados. Las aplicaciones maliciosas pueden controlar la IU del sistema sin la intervención del usuario."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"ampliar la pantalla"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Permite que una aplicación amplíe el contenido de una pantalla. Las aplicaciones malintencionadas pueden transformar el contenido de la pantalla de manera que el dispositivo quede inutilizable."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"cierre parcial"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Pone al administrador de la actividad en estado de cierre. No realiza un cierre completo."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir conmutadores de aplicación"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index cb68b67..d5d9222 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que la aplicación recupere el contenido de la ventana activa. Las aplicaciones malintencionadas pueden recuperar todo el contenido de la ventana y analizar todo el texto de la misma, excepto las contraseñas."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"habilitar la accesibilidad de forma temporal"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permite que una aplicación habilite la accesibilidad en el dispositivo de forma temporal. Las aplicaciones maliciosas pueden habilitar la accesibilidad sin el consentimiento del usuario."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recuperar información de ventanas"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permite que una aplicación recupere información sobre las ventanas del administrador de ventanas. Las aplicaciones malintencionadas pueden recuperar información destinada al uso interno del sistema."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que una aplicación registre un filtro de entrada que filtre el flujo de los eventos del usuario antes de que se envíe. Las aplicaciones malintencionadas pueden controlar la interfaz del sistema sin la intervención del usuario."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"ampliar pantalla"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Permite que una aplicación amplíe el contenido de una pantalla. Las aplicaciones maliciosas pueden transformar el contenido de la pantalla para que el dispositivo no se pueda utilizar."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"cierre parcial"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Pone el administrador de actividades en estado de cierre. No realiza un cierre completo."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar cambios de aplicación"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 039fa9c..12a5ab7 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Võimaldab rakendusel kätte saada aktiivse akna sisu. Pahatahtlikud rakendused võivad hankida kogu akna sisu ja uurida kogu selle teksti, välja arvatud paroole."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ajutine hõlbustuse lubamine"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Lubab rakendusel ajutiselt lubada seadmes hõlbustuse. Pahatahtlikud rakendused võivad lubada hõlbustuse kasutaja nõusolekuta."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"hangi akna teave"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Võimaldab rakendusel hankida teavet aknahalduri akende kohta. Pahatahtlikud rakendused võivad hankida teavet, mis on mõeldud süsteemisiseseks kasutamiseks."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtreeri sündmused"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Võimaldab rakendusel registreerida sisestusfiltri, mis filtreerib kõigi kasutaja sündmuste voo, enne kui need ära saadetakse. Pahatahtlik rakendus võib süsteemi kasutajaliidest juhtida ilma kasutaja sekkumiseta."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"kuva suurendamine"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Lubab rakendusel ekraani sisu suurendada. Pahatahtlikud rakendused võivad muundada kuva sisu nii, et seade muutub ebastabiilseks."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"osaline väljalülitamine"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Lülitab tegevushalduri väljalülitusolekusse. Ei lülita lõplikult välja."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"väldi rakenduste ümberlülitamist"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 308ea59..5cc9697 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"به برنامه اجازه میدهد تا محتوای پنجره فعال را بازیابی کند. برنامههای مخرب میتوانند کل محتوای پنجره را بازیابی کنند و همه متن آنرا به غیر از گذرواژهها امتحان کنند."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"قابلیت دسترسی به طور موقت فعال شود"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"به یک برنامه اجازه میدهد به صورت موقت قابلیت دسترسی را در دستگاه فعال کند. برنامههای مخرب میتوانند قابلیت دسترسی را بدون رضایت کاربر فعال کنند."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"بازیابی اطلاعات پنجره"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"به یک برنامه کاربردی اجازه میدهد که اطلاعات مربوط به پنجرهها را از مدیریت پنجره بازیابی کند. برنامههای کاربردی مخرب ممکن است اطلاعاتی که برای استفاده سیستم داخلی درنظر گرفته شدهاند را بازیابی کنند."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"فیلتر کردن رویدادها"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"به یک برنامه کاربردی اجازه میدهد یک فیلتر ورودی را که جریان تمام رویدادهای کاربران را قبل از ارسال شدن فیلتر میکند، ثبت نماید. برنامه کاربردی مخرب ممکن است رابط کاربری سیستم را بدون مداخله کاربر، کنترل کند."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"بزرگ کردن صفحه نمایش"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"به یک برنامه کاربردی اجازه بزرگ کردن محتوای یک صفحه نمایش را میدهد. برنامههای کاربردی مضر میتوانند محتوای صفحه نمایش را به طریقی منتقل کنند که باعث غیرقابلاستفاده شدن دستگاه شود."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"خاموش شدن جزئی"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"مدیر فعالیت را در حالت خاموشی قرار میدهد. خاموشی را به صورت کامل انجام نمیدهد."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ممانعت از جابجایی برنامه"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index fe3c4617..db118b4 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Antaa sovelluksen noutaa aktiivisen ikkunan sisällön. Haitalliset sovellukset voivat noutaa koko ikkunan sisällön ja tarkastella sen kaikkea tekstiä lukuun ottamatta salasanoja."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ota esteettömyystila käyttöön väliaikaisesti"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Antaa sovelluksen ottaa esteettömyystilan käyttöön laitteessa väliaikaisesti. Haitalliset sovellukset voivat ottaa esteettömyystilan käyttöön ilman käyttäjän lupaa."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"nouda ikkunoiden tietoja"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Antaa sovelluksen noutaa ikkunoiden tietoja ikkunanhallinnasta. Haitalliset sovellukset voivat noutaa tietoja, jotka on tarkoitettu järjestelmän sisäiseen käyttöön."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"suodata tapahtumat"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Antaa sovelluksen rekisteröidä syöttösuodattimen, joka suodattaa kaikkien käyttäjätapahtumien streamin ennen tapahtumien näyttämistä. Haitalliset sovellukset voivat hallita järjestelmän käyttöliittymää ilman käyttäjän lupaa."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"suurenna ruutu"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Antaa sovelluksen suurentaa ruudun sisällön. Haitalliset sovellukset voivat muuttaa näytettävää sisältöä siten, ettei laitetta enää voi käyttää."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"sulje puhelin osittain"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Asettaa toimintojen hallinnan sulkeutumistilaan. Ei sulje puhelinta kokonaan."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"estä sovellusten vaihto"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index acf58ca..9cf9a45 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permet à l\'application de récupérer le contenu de la fenêtre active. Des applications malveillantes peuvent exploiter cette fonctionnalité pour récupérer et lire la totalité du contenu de la fenêtre, à l\'exception des mots de passe."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"activer temporairement l\'accessibilité"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permet à une application d\'activer temporairement l\'accessibilité sur l\'appareil. Des applications malveillantes peuvent activer l\'accessibilité sans le consentement de l\'utilisateur."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"récupérer les données sur les fenêtres"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permet à une application de récupérer les données sur les fenêtres dans le gestionnaire de fenêtres. Des applications malveillantes peuvent récupérer des données destinées à un usage interne du système."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtrer les événements"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Permet à une application d\'enregistrer un filtre d\'entrée pour filtrer le flux de tous les événements des utilisateurs avant qu\'ils ne soient traités. Des applications malveillantes peuvent contrôler l\'interface utilisateur du système sans l\'intervention de l\'utilisateur."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"agrandir l\'écran"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Permet à une application d\'agrandir le contenu à l\'écran. Les applications malveillantes peuvent transformer ce contenu et rendre l\'appareil inutilisable."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"arrêt partiel"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Place le gestionnaire d\'activités en état d\'arrêt, mais n\'effectue pas d\'arrêt complet."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"empêcher les changements d\'applications"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index bcba168..b10bd342 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permet à l\'application de récupérer le contenu de la fenêtre active. Des applications malveillantes peuvent exploiter cette fonctionnalité pour récupérer et lire la totalité du contenu de la fenêtre, à l\'exception des mots de passe."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"activer temporairement l\'accessibilité"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permet à une application d\'activer temporairement l\'accessibilité sur l\'appareil. Des applications malveillantes peuvent activer l\'accessibilité sans le consentement de l\'utilisateur."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"récupérer les informations sur les fenêtres"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permet à une application de récupérer les informations sur les fenêtres depuis le gestionnaire de fenêtres. Des applications malveillantes peuvent récupérer des informations destinées à un usage interne du système."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtrer les événements"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Permet à une application d\'enregistrer un filtre d\'entrée pour filtrer le flux de tous les événements des utilisateurs avant qu\'ils ne soient traités. Des applications malveillantes peuvent contrôler l\'interface utilisateur du système sans l\'intervention de l\'utilisateur."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"agrandir l\'écran"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Permet à une application d\'agrandir le contenu à l\'écran. Les applications malveillantes peuvent transformer ce contenu et rendre l\'appareil inutilisable."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"arrêt partiel"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Place le gestionnaire d\'activités en état d\'arrêt. N\'effectue pas un arrêt complet."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"empêcher les changements d\'applications"</string>
@@ -719,7 +715,7 @@
<item msgid="7897544654242874543">"Bureau"</item>
<item msgid="1103601433382158155">"Télécopie bureau"</item>
<item msgid="1735177144948329370">"Télécopie domicile"</item>
- <item msgid="603878674477207394">"Pager"</item>
+ <item msgid="603878674477207394">"Bipeur"</item>
<item msgid="1650824275177931637">"Autre"</item>
<item msgid="9192514806975898961">"Personnalisé"</item>
</string-array>
@@ -762,7 +758,7 @@
<string name="phoneTypeWork" msgid="8863939667059911633">"Bureau"</string>
<string name="phoneTypeFaxWork" msgid="3517792160008890912">"Télécopie bureau"</string>
<string name="phoneTypeFaxHome" msgid="2067265972322971467">"Télécopie domicile"</string>
- <string name="phoneTypePager" msgid="7582359955394921732">"Pager"</string>
+ <string name="phoneTypePager" msgid="7582359955394921732">"Bipeur"</string>
<string name="phoneTypeOther" msgid="1544425847868765990">"Autre"</string>
<string name="phoneTypeCallback" msgid="2712175203065678206">"Rappel"</string>
<string name="phoneTypeCar" msgid="8738360689616716982">"Voiture"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 05e5941..62c4576 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"ऐप्स को सक्रिय विंडो की सामग्री पुनर्प्राप्त करने देता है. दुर्भावनापूर्ण ऐप्स विंडो की संपूर्ण सामग्री प्राप्त कर सकते हैं और पासवर्ड को छोड़कर इसके सभी पाठ जांच सकते हैं."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"आसान तरीका को अस्थायी रूप से सक्षम करें"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"ऐप्स को उपकरण पर आसान तरीका को अस्थायी रूप से सक्षम करने देता है. दुर्भावनापूर्ण ऐप्स उपयोगकर्ता की सहमति के बिना आसान तरीका को सक्षम कर सकते हैं."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"विंडो जानकारी प्राप्त करें"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"ऐप्स को विंडो प्रबंधक से windows के बारे में जानकारी प्राप्त करने देता है. दुर्भावनापूर्ण ऐप्स आंतरिक सिस्टम उपयोग के लिए अभिप्रेत जानकारी को प्राप्त कर सकते हैं."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"ईवेंट फ़िल्टर करें"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"ऐप्स को इनपुट फ़िल्टर पंजीकृत करने देता है, जो सभी उपयोगकर्ता ईवेंट के स्ट्रीम को भेजे जाने से पहले फ़िल्टर करता है. दुर्भावनापूर्ण ऐप्स उपयोगकर्ता के हस्तक्षेप के बिना सिस्टम UI को नियंत्रित कर सकता है."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"डिस्प्ले को आवर्धित करें"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"ऐप्स को डिस्प्ले की सामग्री आवर्धित करने देता है. दुर्भावनापूर्ण ऐप्स डिस्प्ले सामग्री को इस तरह से बदल सकते हैं कि उपकरण अनुपयोगी रेंडर होता है."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"आंशिक शटडाउन"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"गतिविधि प्रबंधक को शटडाउन स्थिति में रखता है. पूर्ण शटडाउन निष्पादित नहीं करता है."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ऐप्स स्विच करने से रोकता है"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 19afc6c..fc2601b 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Omogućuje aplikaciji dohvaćanje sadržaja aktivnog prozora. Zlonamjerne aplikacije mogu dohvatiti sav sadržaj prozora i pregledati sav njegov tekst osim zaporki."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"privremeno omogući dostupnost"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Aplikacija može privremeno omogućiti dostupnost na uređaju. Zlonamjerne aplikacije mogu omogućiti dostupnost bez korisnikova odobrenja."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"dohvaćanje informacija o prozoru"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Aplikaciji omogućuje dohvaćanje informacija o prozorima iz upravitelja prozora. Zlonamjerne aplikacije mogu dohvaćati informacije koje su namijenjene za internu uporabu sustava."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtriranje događaja"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Aplikaciji omogućuje registraciju ulaznog filtra koji filtrira strujanje svih korisničkih događaja prije otpreme. Zlonamjerne aplikacije mogu kontrolirati korisničko sučelje sustava bez znanja korisnika."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"uvećaj prikaz"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Omogućuje aplikaciji uvećavanje sadržaja zaslona. Zlonamjerne aplikacije mogu izmijeniti sadržaj zaslona tako da uređaj postane neupotrebljiv."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"djelomično isključivanje"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Postavlja upravitelja za aktivnost u stanje mirovanja. Ne isključuje ga u potpunosti."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"sprečavanje promjene aplikacije"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index b40117b..c0effd2 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Lehetővé teszi az alkalmazás számára az aktív ablak tartalmának letöltését. A rosszindulatú alkalmazások letölthetik az ablak teljes tartalmát, és a jelszavak kivételével az összes szöveget megvizsgálhatják."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Ideiglenes hozzáférés engedélyezése"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Engedélyezi egy alkalmazás számára, hogy ideiglenesen hozzáférést biztosítson az eszközhöz. A kártékony alkalmazások a felhasználó beleegyezése nélkül engedélyezhetik a hozzáférést."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"ablakkal kapcsolatos információk lekérése"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Lehetővé teszi, hogy az alkalmazás információkat kérjen le az ablakkezelőben lévő ablakokkal kapcsolatban. A rosszindulatú alkalmazások belső rendszerhasználathoz szükséges információkat kérhetnek le."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"események szűrése"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Lehetővé teszi az alkalmazás számára, hogy egy bemeneti szűrőt használjon, amely megszűri a falon megjelenő felhasználói eseményeket, még mielőtt megjelennének. A rosszindulatú alkalmazások felhasználói beavatkozás nélkül irányíthatják a rendszer kezelőfelületét."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"kijelző nagyítása"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Lehetővé teszi egy alkalmazás számára, hogy kinagyítsa a kijelzőn megjelenő tartalmat. Előfordulhat, hogy a rosszindulatú alkalmazások úgy alakítják át a kijelző tartalmát, hogy használhatatlanná válik az eszköz."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"részleges rendszerleállítás"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Leállítás állapotba helyezi a tevékenységkezelőt. Nem hajtja végre a teljes leállítást."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"alkalmazásváltás megakadályozása"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 62464ba..29a8d07 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Թույլ է տալիս հավելվածին առբերել ակտիվ պատուհանի պարունակությունը: Վնասարար հավելվածները կարող են առբերել պատուհանի լրիվ պարունակությունը և հետազոտել դրա ամբողջ տեքստը` բացառությամբ գաղտնաբառերի:"</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ժամանակավոր միացնել մուտքի հնարավորությունը"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Թույլ է տալիս հավելվածին ժամանակավորապես մուտքի հնարավորություն տալ սարքին: Վնասարար հավելվածները կարող են մուտքի հնարավորություն ընձեռել առանց օգտվողի համաձայնության:"</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"առբերել պատուհանի տեղեկություները"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Թույլ է տալիս հավելվածին առբերել պատուհանների մասին տեղեկատվություններ պատուհանի կառավարչից: Վնասարար հավելվածները կարող են առբերել տեղեկություններ, որը նախատեսված է ներքին համակարգի օգտագործման համար:"</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"զտել իրադարձությունները"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Թույլ է տալիս հավելվածին գրանցել մուտքագրման զտիչ, որը զտում է օգտվողի իրադարձությունների ամբողջ հոսքը` նախքան դրանք կուղարկվեն: Վնասարար հավելվածը կարող է կառավարել համակարգի UI-ը` առանց ձեր միջամտության:"</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"խոշորացնել ցուցադրիչը"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Թույլ է տալիս հավելվածին խոշորացնել ցուցադրիչի բովանդակությունը: Վնասարար հավելվածները կարող են փոխակերպել ցուցադրիչի բովանդակությունը այնպես, որ սարքը դառնա անպիտան:"</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"մասնակի անջատում"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Դնում է գործունեության կառավարչին անջատման կարգավիճակի մեջ: Չի իրականացնում ամբողջական անջատում:"</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"կանխել ծրագրի փոխարկումները"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index b3b0d2b..71fd308 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Mengizinkan apl mengambil konten jendela aktif. Apl berbahaya dapat mengambil seluruh konten jendela dan memeriksa semua teksnya kecuali sandi."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"aktifkan aksesibilitas untuk sementara"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Memungkinkan aplikasi mengaktifkan aksesibilitas pada perangkat untuk sementara. Aplikasi berbahaya dapat mengaktifkan aksesibilitas tanpa izin pengguna."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"mengambil info jendela"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Mengizinkan aplikasi mengambil informasi tentang jendela dari pengelola jendela. Aplikasi berbahaya dapat mengambil informasi yang ditujukan untuk penggunaan sistem internal."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"memfilter acara"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Mengizinkan aplikasi mendaftarkan filter masukan yang memfilter streaming semua acara pengguna sebelum acara dikirimkan. Aplikasi berbahaya dapat mengontrol UI sistem tanpa campur tangan pengguna."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"memperbesar tampilan"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Izinkan aplikasi memperbesar konten tampilan. Aplikasi berbahaya dapat mengubah konten tampilan dengan merender perangkat menjadi tidak dapat digunakan."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"penghentian sebagian"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Letakkan pengelola aktivitas dalam kondisi mati. Tidak melakukan penonaktifan penuh."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"cegah pergantian aplikasi"</string>
@@ -983,7 +979,7 @@
<string name="save_password_remember" msgid="6491879678996749466">"Ingat"</string>
<string name="save_password_never" msgid="8274330296785855105">"Jangan"</string>
<string name="open_permission_deny" msgid="7374036708316629800">"Anda tidak memiliki izin untuk membuka laman ini."</string>
- <string name="text_copied" msgid="4985729524670131385">"Teks disalin ke clipboard."</string>
+ <string name="text_copied" msgid="4985729524670131385">"Teks disalin ke papan klip."</string>
<string name="more_item_label" msgid="4650918923083320495">"Lainnya"</string>
<string name="prepend_shortcut_label" msgid="2572214461676015642">"Menu+"</string>
<string name="menu_space_shortcut_label" msgid="2410328639272162537">"spasi"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 3faca1a..958f34c 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Consente all\'applicazione di recuperare i contenuti della finestra attiva. Le applicazioni dannose potrebbero recuperare l\'intero contenuto della finestra ed esaminare tutto il testo, tranne le password."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"attivazione temporanea dell\'accessibilità"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Consente a un\'applicazione di attivare temporaneamente l\'accessibilità sul dispositivo. Le applicazioni dannose potrebbero attivare l\'accessibilità senza il consenso dell\'utente."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recupero di informazioni sulle finestre"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Consente a un\'applicazione di recuperare informazioni sulle finestre dalla gestione finestre. Le applicazioni dannose potrebbero recuperare informazioni destinate all\'utilizzo da parte del sistema interno."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtro eventi"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Consente a un\'applicazione di registrare un filtro di ingresso che filtra lo stream di tutti gli eventi degli utenti prima che vengano inviati. Un\'applicazione dannosa potrebbe controllare l\'interfaccia utente del sistema senza l\'intervento dell\'utente."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"ingrandimento dello schermo"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Consente a un\'applicazione di ingrandire i contenuti di uno schermo. Le applicazioni dannose potrebbero trasformare i contenuti dello schermo in modo da rendere inutilizzabile il dispositivo."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"chiusura parziale"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Mette il gestore delle attività in uno stato di chiusura. Non esegue una chiusura completa."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedire commutazione applicazione"</string>
@@ -458,7 +454,7 @@
<string name="permlab_writeCallLog" msgid="8552045664743499354">"scrittura del registro chiamate"</string>
<string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Consente all\'applicazione di modificare il registro chiamate del tablet, inclusi i dati sulle chiamate in arrivo e in uscita. Le applicazioni dannose potrebbero farne uso per cancellare o modificare il registro chiamate."</string>
<string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Consente all\'applicazione di modificare il registro chiamate del telefono, inclusi i dati sulle chiamate in arrivo e in uscita. Le applicazioni dannose potrebbero farne uso per cancellare o modificare il registro chiamate."</string>
- <string name="permlab_readProfile" msgid="4701889852612716678">"lettura scheda cont. personale"</string>
+ <string name="permlab_readProfile" msgid="4701889852612716678">"lettura scheda contatti pers."</string>
<string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Consente all\'applicazione di leggere informazioni del profilo personale memorizzate sul dispositivo, come il tuo nome e le tue informazioni di contatto. Ciò significa che l\'applicazione può identificarti e inviare le informazioni del tuo profilo ad altri."</string>
<string name="permlab_writeProfile" msgid="907793628777397643">"modifica scheda contatti"</string>
<string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Consente all\'applicazione di modificare o aggiungere informazioni ai dati del profilo personale memorizzati sul dispositivo, come il tuo nome e le tue informazioni di contatto. Significa che l\'applicazione può identificarti e inviare le informazioni del tuo profilo ad altri."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index f330aaa..9ecc437 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -163,7 +163,7 @@
<string name="global_action_lock" msgid="2844945191792119712">"נעילת מסך"</string>
<string name="global_action_power_off" msgid="4471879440839879722">"כיבוי"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"דיווח על באג"</string>
- <string name="bugreport_title" msgid="2667494803742548533">"מלא דיווח על באג"</string>
+ <string name="bugreport_title" msgid="2667494803742548533">"שלח דיווח על באג"</string>
<string name="bugreport_message" msgid="398447048750350456">"פעולה זו תאסוף מידע על מצב המכשיר הנוכחי שלך על מנת לשלוח אותו כהודעת דוא\"ל. היא תימשך זמן קצר מרגע פתיחת דיווח הבאג ועד שיהיה ניתן לבצע שליחה. התאזר בסבלנות."</string>
<string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"מצב שקט"</string>
<string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"הקול כבוי"</string>
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"מאפשר לאפליקציה לאחזר את התוכן של החלון הפעיל. אפליקציות זדוניות עלולות לאחזר את תוכן החלון כולו ולבחון את כל הטקסט שבו, מלבד סיסמאות."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"הפעלת נגישות זמנית"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"מאפשר לאפליקציה להפעיל באופן זמני נגישות במכשיר. אפליקציות זדוניות עלולות לאפשר נגישות ללא הסכמת משתמש."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"אחזר מידע חלון"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"מאפשר לאפליקציה לאחזר מידע לגבי החלונות ממנהל החלונות. אפליקציות זדוניות עשויות לאחזר מידע המיועד לשימוש מערכת פנימי."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"סנן אירועים"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"מאפשר לאפליקציה לרשום מסנן קלט שמסנן את הזרם של כל אירועי המשתמש לפני שהם נשלחים. אפליקציה זדונית עשויה לשלוט ב-UI של המערכת ללא התערבות משתמש."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"הגדלת תצוגה"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"מאפשר לאפליקציה להגדיל את התוכן של תצוגה. אפליקציות זדוניות עלולות לשנות את תוכן התצוגה כך שהמכשיר יהפוך לבלתי שמיש."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"כיבוי חלקי"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"מעביר את מנהל הפעילויות למצב כיבוי. לא מבצע כיבוי מלא."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"מנע החלפת אפליקציות"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 4a26208..a75ee90 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"作業中のウィンドウの内容を取得することをアプリに許可します。この許可を悪意のあるアプリに利用されると、ウィンドウの内容全体が取得されてパスワード以外のテキストがすべてチェックされる恐れがあります。"</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ユーザー補助を一時的に有効にする"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"この端末のユーザー補助を一時的に有効にすることをアプリに許可します。悪意のあるアプリはユーザーの同意を得ずにユーザー補助を有効にする場合があります。"</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"ウィンドウ情報の取得"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"ウィンドウマネージャからウィンドウに関する情報を取得することをアプリに許可します。悪意のあるアプリが内部システムの利用を目的に情報を取得する恐れがあります。"</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"イベントのフィルタリング"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"すべてのユーザーイベントが送られる前にストリームをフィルタリングする入力フィルタを登録することをアプリに許可します。悪意のあるアプリがユーザーの操作なしでシステムUIを制御する恐れがあります。"</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"表示の拡大"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"表示内容を拡大することをアプリに許可します。悪意のあるアプリが、端末を使用できなくなるように表示内容を変換する恐れがあります。"</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"部分的にシャットダウンする"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"アクティビティマネージャをシャットダウン状態にします。完全なシャットダウンは実行しません。"</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"アプリケーションの切り替えを禁止する"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 5dbb83f..15abf53 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"აპს შეეძლება აქტიური ფანჯრიდან კონტენტის მოძიება. მავნე აპებს შეუძლიათ ფანჯრის სრული კონტენტის მოძიება და ყველა ტექსტის წაკითხვა პაროლების გარდა."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"მარტივი წვდომის დროებით გააქტიურება"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"აპს შეეძლება მოწყობილობაზე გამარტივებული რეჟიმის ჩართვა. მავნე აპებს შეეძლებათ ამ რეჟიმის ჩართვა მომხმარებლის გაფრთხილების გარეშე."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"ფანჯრის ინფორმაციის მოძიება"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"აპს შეეძლება ფანჯრების მენეჯერის მეშვეობით ფანჯრების შესახებ ინფორმაციის მოპოვება. მავნე აპლიკაციებს შეეძლებათ ისეთი ინფორმაციის მოპოვება, რომელიც შიდა სისტემური მოხმარებისთვის არის განკუთვნილი."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"ღონისძიებების გაფილტვრა"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"აპლიკაციას შეეძლება რეგისტრაცია შეტანის ფილტრებისა, რომლებიც ასუფთავებენ მომხმარებლის ღონისძიების ყველა დინებას. მავნე აპმა შესაძლოა ეს ფუნქცია სისტემის UI კონტროლისთვის გამოიყენოს, მომხმარებლის ინტერვენციის გარეშე."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"ეკრანის გადიდება"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"აპლიკაციას შეეძლება, შეცვალოს დისპლეის კონტენტი. მავნე აპებმა შეიძლება იმგვარად გარდაქმნან დისპლეის კონტენტი, რომ მოწყობილობა გამოუსადეგარი გახდეს."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"ნაწილობრივი გამორთვა"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"აქტივობების მენეჯერს გათიშვის რეჟიმში აყენებს. სრულ გათიშვას არ ახორციელებს."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"აპის გადართვებისგან დაცვა"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 21a7746..c2ff0e8 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"ឲ្យកម្មវិធីទៅយកមាតិកាបង្អួចសកម្ម។ កម្មវិធីព្យាបាទអាចទៅយកមាតិកាបង្អួចទាំងមូល និងពិនិត្យអត្ថបទទាំងអស់ លើកលែងតែពាក្យសម្ងាត់។"</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"បើកមធ្យោបាយងាយស្រួលជាបណ្ដោះអាសន្ន"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"ឲ្យកម្មវិធីបើកភាពងាយស្រួលលើឧបករណ៍ជាបណ្ដោះអាសន្ន។ កម្មវិធីព្យាបាទអាចបើកភាពងាយស្រួលដោយមិនឲ្យអ្នកប្រើដឹង។"</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"ទៅយកព័ត៌មានបង្អួច"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"ឲ្យកម្មវិធី ទៅយកព័ត៌មានអំពីបង្អួចពីកម្មវិធីគ្រប់គ្រងបង្អួច។ កម្មវិធីព្យាបាទអាចទៅយកព័ត៌មានដែលមានបំណងសម្រាប់ការប្រើប្រព័ន្ធខាងក្នុង។"</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"ច្រោះព្រឹត្តិការណ៍"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"ឲ្យកម្មវិធីចុះឈ្មោះតម្រងបញ្ចូលដែលច្រោះព្រឹត្តិការណ៍របស់អ្នកប្រើទាំងអស់មុនពេលពួកវាត្រូវបានផ្ដាច់។ កម្មវិធីព្យាបាទអាចពិនិត្យចំណុចប្រទាក់ប្រព័ន្ធដោយគ្មានអំពើពីអ្នកប្រើ។"</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"ពង្រីកការបង្ហាញ"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"ឲ្យកម្មវិធីពង្រីកមាតិកានៃការបង្ហាញ។ កម្មវិធីព្យាបាទអាចប្ដូរមាតិកាការបង្ហាញតាមវិធីដែលបង្ហាញថាឧបករណ៍មិនអាចប្រើបាន។"</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"បិទដោយផ្នែក"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"ដាក់កម្មវិធីគ្រប់គ្រងសកម្មភាពក្នុងស្ថានភាពបិទ។ មិនអនុវត្តការបិទពេញលេញទេ។"</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ការពារការប្ដូរកម្មវិធី"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 9e46527..8d8eb88 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"앱이 활성 창의 콘텐츠를 검색할 수 있도록 허용합니다. 이 경우 악성 앱이 전체 창의 콘텐츠를 검색하여 비밀번호를 제외한 모든 텍스트를 살펴볼 수 있습니다."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"일시적인 접근성 사용"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"애플리케이션이 기기에서 일시적으로 접근성을 사용하도록 허용합니다. 이 경우 악성 앱이 사용자의 동의 없이 접근성을 사용할 수 있습니다."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"창 관련 정보 가져오기"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"애플리케이션이 Window Manager에서 창 관련 정보를 가져오도록 허용합니다. 이 경우 악성 앱이 내부 시스템에서만 사용하도록 되어 있는 정보를 가져올 수 있습니다."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"일정 필터링"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"애플리케이션에 입력 필터를 등록할 수 있도록 하여 모든 사용자 일정 스트림을 전달하기 전에 필터링합니다. 이 경우 사용자의 개입 없이 악성 앱이 시스템 UI를 제어할 수 있습니다."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"디스플레이 확대"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"앱이 표시된 콘텐츠를 확대하도록 허용합니다. 악성 앱은 표시된 콘텐츠를 변형시켜 기기를 사용할 수 없게 만들 수 있습니다."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"부분 종료"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"작업 관리자를 종료 상태로 설정합니다. 전체 종료를 수행하지는 않습니다."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"애플리케이션 전환 방지"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 56a05c3..3b31a8e 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"ອະນຸຍາດໃຫ້ແອັບຯດຶງຂໍ້ມູນເນື້ອຫາຂອງໜ້າຈໍທີ່ໃຊ້ຢູ່ໄດ້. ແອັບຯທີ່ເປັນອັນຕະລາຍອາດດຶງຂໍ້ມູນທັງໝົດໃນໜ້າຈໍ ແລະກວດສອບຂໍ້ຄວາມທັງໝົດໃນນັ້ນໄດ້ ຍົກເວັ້ນລະຫັດຜ່ານ."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ປິດການຊ່ວຍການເຂົ້າເຖິງຊົ່ວຄາວ"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນ ເປີດໃຊ້ການຊ່ວຍເຂົ້າເຖິງແບບຊົ່ວຄາວໃນອຸປະກອນ. ແອັບຯທີ່ເປັນອັນຕະລາຍ ອາດເປີດໃຊ້ການຊ່ວຍເຂົ້າເຖິງ ໂດຍບໍ່ໄດ້ຮັບການຍິນຍອມຈາກຜູ່ໃຊ້."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"ດຶງເອົາຂໍ້ມູນໜ້າຈໍ"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນ ດຶງເອົາຂໍ້ມູນກ່ຽວກັບໜ້າຈໍຈາກໂຕຈັດການໜ້າຈໍ. ແອັບຯທີ່ບໍ່ປອດໄພອາດດຶງເອົາຂໍ້ມູນທີ່ໃຊ້ສຳລັບພາຍໃນລະບົບໄດ້."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"ກັ່ນຕອງເຫດການ"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນ ລົງທະບຽນການກັ່ນຕອງຂາເຂົ້າ ທີ່ກັ່ນຕອງການສົ່ງຂໍ້ມູນເຫດການຜູ່ໃຊ້ທັງໝົດ ກ່ອນທີ່ພວກມັນຈະຖືກເຜີຍແຜ່. ແອັບຯທີ່ເປັນອັນຕະລາຍອາດຄວບຄຸມ UI ຂອງລະບົບໂດຍບໍ່ຕ້ອງໃຫ້ຜູ່ໃຊ້ຈັດການໄດ້."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"ຂະຫຍາຍການສະແດງຜົນ"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນ ສາມາດຂະຫຍາຍເນື້ອຫາທີ່ສະແດງຜົນໄດ້. ແອັບພລິເຄຊັນທີ່ເປັນອັນຕະລາຍ ອາດປ່ຽນເນື້ອຫາທີ່ສະແດງໃນລັກສະນະ ທີ່ເຮັດໃຫ້ບໍ່ສາມາດນຳໃຊ້ອຸປະກອນໄດ້."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"ປິດລົງບາງສ່ວນ"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"ກຳນົດໃຫ້ໂຕຈັດການກິດຈະກຳຢູ່ໃນສະຖານະປິດລະບົບ ໂດຍບໍ່ໄດ້ປິດລະບົບຢ່າງສົມບູນ."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ຂັດຂວາງການສະລັບແອັບຯ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 4284032..9c01d99 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Leidžiama programai nuskaityti aktyvaus lango turinį. Kenkėjiškos programos gali bandyti išgauti viso lango turinį ir tirti visą jo tekstą, išskyrus slaptažodžius."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"laikinai įgalinti pritaikymą neįgaliesiems"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Leidžiama programai laikinai įgalinti pritaikymą neįgaliesiems įrenginyje. Kenkėjiškos programos pritaikymą neįgaliesiems gali įgalinti be naudotojo sutikimo."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"gauti lango informaciją"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Leidžiama programai iš langų tvarkytuvės gauti informaciją apie langus. Kenkėjiškos programos gali gauti informaciją, kuri skirta naudoti sistemos viduje."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtrų įvykiai"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Leidžiama programai registruoti įvesties filtrą, kuriuo filtruojamas visų naudotojo įvykių srautas prieš juos išsiunčiant. Kenkėjiška programa gali kontroliuoti sistemos naudotojo sąsają be naudotojo įsikišimo."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"didinti pateiktį"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Leidžiama programai didinti pateikties turinį. Kenkėjiškos programos gali pakeisti pateikties turinį taip, kad nebūtų galima naudoti įrenginio."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"dalinis išjungimas"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Veiklos tvarkyklę perjungia į išsijungimo būseną. Neišjungia visiškai."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"neleisti perjungti programų"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 4a207d9..478c32d 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Ļauj lietotnei izgūt aktīva loga saturu. Ļaunprātīgas lietotnes var izgūt visu loga saturu un pārbaudīt visu tā tekstu, izņemot paroles."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Īslaicīga pieejamības režīma iespējošana"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Ļauj lietojumprogrammai īslaicīgi ierīcē iespējot pieejamības režīmu. Ļaunprātīgas lietotnes var iespējot pieejamības režīmu bez lietotāja atļaujas."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"Izgūt informāciju par logiem"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Ļauj lietojumprogrammai no logu pārvaldnieka izgūt informāciju par logiem. Ļaunprātīgas lietotnes var izgūt informāciju, kas ir paredzēta iekšējai izmantošanai sistēmā."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"Filtrēt notikumus"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Ļauj lietojumprogrammai reģistrēt ieejas filtru, kas filtrē visu lietotāja notikumu straumi, pirms notikumi tiek nosūtīti. Ļaunprātīga lietotne var kontrolēt sistēmas lietotāja saskarni, nejautājot lietotājam."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"displeja palielināšana"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Ļauj lietojumprogrammai palielināt displeja saturu. Ļaunprātīgas lietotnes var pārveidot displeja saturu tā, ka ierīce kļūst nelietojama."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"daļēja izslēgšana"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Liek darbību pārvaldniekam pāriet izslēgšanas stāvoklī. Neveic pilnīgu izslēgšanu."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"novērst lietojumprogrammu pārslēgšanu"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 5e60ce3..a587992 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Апп нь идэвхтэй цонхны контентыг авах боломжтой. Хортой апп нь цонхны контентыг бүхэлд авах болон нууц үгнээс бусад бүх текстийг шалгаж болзошгүй"</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Хялбар байдлыг түр идэвхтэй болгох"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Аппликешн нь төхөөрөмжийн хялбар байдлыг түр зуур идэвхжүүлэх боломжтой. Хортой апп нь хэрэглэгчийн зөвшөөрөлгүйгээр хялбар байдлыг идэвхжүүлж болзошгүй."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"цонхны мэдээллийг унших"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Аппликешн нь цонхны менежерээс цонхны талаар мэдээллийг дуудах боломжтой. Хортой апп нь дотоод системийн хэрэглээнд зориулагдсан мэдээллийг дуудаж болзошгүй."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"үйл явдлыг шүүх"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Аппликешн нь хэрэглэгчийн бүх үйл явдалын илгээгдэхээс өмнөх урсгалыг шүүж байгаа оролтын шүүлтйиг бүртгэх боломжтой. Хортой апп нь хэрэглэгчийн интервэшнгүйгээр системийн UI-г удирдах боломжтой."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"дэлгэц томруулах"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Аппликешн нь дэлгэцний контентийг өсгөх боломжтой. Хортой апп нь дэлгэцийн контентыг төхөөрөмжнөөс ашиглаж болохгүй болгон хувиргах боломжтой."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"хэсэгчилсэн унтраалт"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Активити менежерийг унтраана. Бүрэн унтраалтыг хийхгүй."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"апп шилжүүлэхийг хориглох"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index c1b7cdb..dbf6004 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Membenarkan apl untuk mendapatkan kandungan tetingkap aktif. Apl hasad boleh mengambil keseluruhan kandungan tetingkap dan memeriksa semua teks kecuali kata laluan."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"dayakan kebolehcapaian untuk sementara"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Membenarkan aplikasi untuk mendayakan kebolehcapaian untuk sementara pada peranti. Apl hasad mungkin mendayakan kebolehcapaian tanpa izin pengguna."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"dapatkan maklumat tetingkap"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Membolehkan aplikasi mendapatkan maklumat tentang tetingkap dari pengurus tetingkap. Apl hasad boleh mendapatkan maklumat yang bertujuan untuk penggunaan sistem dalaman."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"tapis acara"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Membenarkan aplikasi mendaftarkan penapis input yang menapis strim semua acara pengguna sebelum dihantar. Apl hasad mungkin mengawal UI sistem tanpa campur tangan pengguna."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"besarkan paparan"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Membenarkan aplikasi membesarkan kandungan paparan. Apl hasad mungkin mengubah kandungan paparan yang akan membuatkan peranti tidak boleh digunakan."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"penutupan separa"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Meletakkan pengurus aktiviti dalam keadaan tutup. Tidak melaksanakan penutupan lengkap."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"halang pertukaran apl"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index c1cd604..12d18e0 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Lar appen hente ut innholdet i det aktive vinduet. Ondsinnede apper kan hente ut hele vindusinnholdet og undersøke all teksten, med unntak av passord."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"aktivere tilgjengelighet midlertidig"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Lar en app midlertidig aktivere tilgjengelighet på enheten. Skadelige apper kan aktivere tilgjengelighet uten bekreftelse fra brukeren."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"hente vindusinformasjon"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Lar appen hente informasjon om vinduene fra vindusbehandleren. Skadelige apper kan hente informasjon som ikke er ment for intern systembruk."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtrere hendelser"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Lar appen registrere et inndatafilter som filtrerer strømmen for alle brukerhendelser før de sendes ut. Skadelige apper kan kontrollere brukergrensesnittet for systemet uten at brukeren gjør noe."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"forstørre visningen"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Lar apper forstørre innholdet på en skjerm. Skadelige apper kan endre skjerminnhold på en måte som gjør at enheten blir ubrukelig."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"delvis avslutning"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Lar appen sette aktivitetshåndtereren i avslutningstilstand. Slår ikke systemet helt av."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"forhindre bytte mellom apper"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 673df4e..2c02916 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Hiermee kan de app de inhoud van het actieve venster ophalen. Schadelijke apps kunnen de volledige inhoud van het venster ophalen en alle tekst bekijken, behalve wachtwoorden."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"toegankelijkheid tijdelijk inschakelen"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Een app toestaan toegankelijkheid tijdelijk in te schakelen op het apparaat. Schadelijke apps kunnen toegankelijkheid inschakelen zonder toestemming van de gebruiker."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"venstergegevens ophalen"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Toestaan dat een app gegevens over vensters kan ophalen uit vensterbeheer. Schadelijke apps kunnen gegevens ophalen die zijn bedoeld voor interne systeemfunctionaliteit."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"evenementen filteren"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Toestaan dat een app een invoerfilter registreert waarmee de streams van alle gebruikersgebeurtenissen worden gefilterd voordat deze worden verzonden. Schadelijke apps kunnen de gebruikersinterface van het systeem beheren zonder tussenkomst van de gebruiker."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"display vergroten"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Een app toestaan de inhoud van een display te vergroten. Schadelijke apps kunnen de display-inhoud transformeren op een manier waardoor het apparaat onbruikbaar wordt."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"gedeeltelijke uitschakeling"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Hiermee wordt activiteitenbeheer uitgeschakeld. Er wordt geen volledige uitschakeling uitgevoerd."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"schakelen tussen apps voorkomen"</string>
@@ -1511,9 +1507,9 @@
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Overlay <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
<string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", beveiligd"</string>
- <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Scherm sturen"</string>
+ <string name="wifi_display_notification_connecting_title" msgid="2838646471050359706">"Scherm casten"</string>
<string name="wifi_display_notification_connecting_message" msgid="5837350993752841389">"Verbinden met <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Scherm sturen"</string>
+ <string name="wifi_display_notification_connected_title" msgid="8567308065912676285">"Scherm casten"</string>
<string name="wifi_display_notification_connected_message" msgid="2587209325701109715">"Verbonden met <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Verbinding verbreken"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"Noodoproep"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index e9d701a..b2a9184 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -137,7 +137,7 @@
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Pamięć tabletu jest pełna. Usuń niektóre pliki, aby zwolnić miejsce."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Pamięć telefonu jest pełna. Usuń niektóre pliki, aby zwolnić miejsce."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Sieć może być monitorowana"</string>
- <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Przez nieznaną firmę zewnętrzną"</string>
+ <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Przez nieznany podmiot zewnętrzny"</string>
<string name="ssl_ca_cert_noti_managed" msgid="4030263497686867141">"Przez <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string>
<string name="me" msgid="6545696007631404292">"Ja"</string>
<string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opcje tabletu"</string>
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Pozwala aplikacji na pobieranie zawartości aktywnego okna. Złośliwe aplikacje mogą pobrać całą zawartość okna i przeanalizować znajdujący się w nim tekst z wyjątkiem haseł."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"tymczasowo włącz ułatwienia dostępu"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Umożliwia aplikacji tymczasowe włączanie ułatwień dostępu na urządzeniu. Złośliwe aplikacje mogą je włączać bez zgody użytkownika."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"pobieranie informacji o oknach"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Zezwala aplikacji na pobieranie informacji o oknach z menedżera okien. Złośliwe aplikacje mogą pobierać informacje przeznaczone do użytku wewnętrznego w systemie."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtrowanie zdarzeń"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Zezwala aplikacji na zarejestrowanie filtra wejściowego, który filtruje strumień wszystkich zdarzeń z udziałem użytkownika przed ich rozesłaniem. Złośliwe aplikacje mogą kontrolować interfejs systemu niezależnie od działań użytkownika."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"powiększanie ekranu"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Zezwala aplikacji na powiększenie zawartości ekranu. Szkodliwe aplikacje mogą przekształcić zawartość ekranu tak, by urządzenie stało się bezużyteczne."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"częściowe wyłączenie"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Przełącza menedżera aktywności w stan wyłączenia. Nie wykonuje pełnego wyłączenia."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zapobieganie przełączaniu aplikacji"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index cf38b47..3e55c58 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que a aplicação obtenha o conteúdo da janela ativa. As aplicações maliciosas podem obter todo o conteúdo da janela e examinar todo o texto, exceto as palavras-passe."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"acessibilidade ativada temporariamente"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permite que uma aplicação ative temporariamente a acessibilidade no dispositivo. As aplicações maliciosas podem ativar a acessibilidade sem o consentimento do utilizador."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"obter informações da janela"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permite que uma aplicação obtenha informações sobre as janelas a partir do gestor de janelas. Aplicações maliciosas podem obter informações que se destinam à utilização interna do sistema."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que uma aplicação registe um filtro de entrada que filtra a transmissão em fluxo contínuo para todos os eventos de utilizador antes de serem entregues. Uma aplicação maliciosa pode controlar a IU do sistema sem intervenção do utilizador."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"ampliar o visor"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Permite que uma aplicação amplie o conteúdo de um visor. As aplicações maliciosas poderão transformar o conteúdo do visor de um modo que torne o dispositivo inutilizável."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"encerramento parcial"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Coloca o gestor de actividade num estado de encerramento. Não executa um encerramento completo."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir trocas de aplicações"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index d048d51..de22fd5 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que o aplicativo recupere o conteúdo da janela ativa. Aplicativos maliciosos podem recuperar o conteúdo da janela inteira e examinar todo o texto, exceto as senhas."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ativar temporariamente a acessibilidade"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permite que um aplicativo ative temporariamente a acessibilidade no dispositivo. Aplicativos maliciosos podem ativar a acessibilidade sem o consentimento do usuário."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"recuperar informações de janelas"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permite que o aplicativo recupere informações sobre as janelas do gerenciador de janelas. Aplicativos mal-intencionados podem recuperar informações destinadas ao uso interno do sistema."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que o aplicativo registre um filtro de entrada que filtra o fluxo de todos os eventos do usuário antes que sejam enviados. Aplicativos mal-intencionados podem controlar a interface do sistema sem a intervenção do usuário."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"ampliar monitor"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Permite que o aplicativo amplie o conteúdo de um monitor. Aplicativos maliciosos podem manipular o conteúdo do monitor de modo a tornar o dispositivo inutilizável."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"desligamento parcial"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Coloca o gerenciador de atividades em um estado de desligamento. Não executa o desligamento completo."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar trocas de aplicativo"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 8d007e4..6c5344b 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -478,18 +478,10 @@
<skip />
<!-- no translation found for permdesc_temporary_enable_accessibility (8079456293182975464) -->
<skip />
- <!-- no translation found for permlab_retrieve_window_info (8532295199112519378) -->
- <skip />
- <!-- no translation found for permdesc_retrieve_window_info (4998836370424186849) -->
- <skip />
<!-- no translation found for permlab_filter_events (8675535648807427389) -->
<skip />
<!-- no translation found for permdesc_filter_events (8006236315888347680) -->
<skip />
- <!-- no translation found for permlab_magnify_display (5973626738170618775) -->
- <skip />
- <!-- no translation found for permdesc_magnify_display (7121235684515003792) -->
- <skip />
<string name="permlab_shutdown" msgid="7185747824038909016">"serrar parzialmain"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Metta l\'administratur dad activitads en in stadi da pausa. El na vegn betg serrà dal tut."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar il midar tranter applicaziuns"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index dd9dd9e..d4f5183 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite aplicaţiei să preia conţinutul ferestrei active. Aplicaţiile rău intenţionate pot să preia întregul conţinut al ferestrei şi să examineze integral textul acesteia, cu excepţia parolelor."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"activare temporară a accesibilității"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permite unei aplicaţii să activeze temporar accesibilitatea pe gadget. Aplicaţiile rău intenţionate o pot activa fără consimţământul utilizatorului."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"preluare informaţii despre ferestre"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Permite unei aplicaţii să preia informaţii despre ferestrele din managerul de ferestre. Aplicaţiile rău intenţionate pot prelua informaţii care sunt destinate utilizării sistemului intern."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtrare evenimente"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Permite unei aplicaţii să înregistreze un filtru de intrare, care filtrează transmiterea în flux a tuturor evenimentelor utilizatorilor înainte ca acestea să fie expediate. Aplicaţiile rău intenţionate pot controla interfaţa de utilizare a sistemului fără intervenţia utilizatorului."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"măreşte afişajul"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Permite unei aplicaţii să mărească conţinutul unui afişaj. Aplicaţiile rău intenţionate pot transforma conţinutul afişajului într-un mod care ar face inutilizabil dispozitivul."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"închidere parţială"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Plasează Managerul de activităţi într-o stare de închidere. Nu efectuează o închidere completă."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"împiedicare comutare între aplicaţii"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index f518a0c..fd0776b 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -136,7 +136,7 @@
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Слишком много удалений <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Память планшетного ПК заполнена. Удалите какие-нибудь файлы, чтобы освободить место."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Память телефона заполнена. Удалите какие-нибудь файлы, чтобы освободить место."</string>
- <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Действия в сети могут отслеживаться"</string>
+ <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Сеть может отслеживаться"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"администратором"</string>
<string name="ssl_ca_cert_noti_managed" msgid="4030263497686867141">"администратором домена <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string>
<string name="me" msgid="6545696007631404292">"Я"</string>
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Приложение сможет получать контент активного окна. Вредоносные программы смогут перехватывать такой контент и анализировать любой текст, кроме паролей."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Включение специальных возможностей"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Приложение сможет временно включать на устройстве специальные возможности. Вредоносные приложения смогут включать их без вашего ведома."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"Доступ к информации в окне"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Открывает приложению доступ к информации из диспетчера окон. Обратите внимание, что вредоносное ПО может получить доступ к некоторой системной информации устройства."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"Фильтрация событий"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Разрешает приложению зарегистрировать входной фильтр, который анализирует весь поток пользовательских событий. Обратите внимание, что вредоносное ПО может получить доступ к управлению интерфейсом без ведома пользователя."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"Увеличение изображений"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Приложение сможет увеличивать содержимое экрана. Вредоносные программы смогут изменять изображение таким образом, что устройством нельзя будет пользоваться."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"Частичное завершение работы"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Завершает работу диспетчера активности. Не выполняет полное завершение работы."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"Защита от переключения приложений"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 4df9785..899c4f9 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -145,7 +145,7 @@
<string name="silent_mode" msgid="7167703389802618663">"Tichý režim"</string>
<string name="turn_on_radio" msgid="3912793092339962371">"Zapnúť bezdrôtové pripojenie"</string>
<string name="turn_off_radio" msgid="8198784949987062346">"Vypnúť bezdrôtové pripojenie"</string>
- <string name="screen_lock" msgid="799094655496098153">"Uzamknutie obrazovky"</string>
+ <string name="screen_lock" msgid="799094655496098153">"Zámka obrazovky"</string>
<string name="power_off" msgid="4266614107412865048">"Vypnúť"</string>
<string name="silent_mode_silent" msgid="319298163018473078">"Zvonenie je vypnuté"</string>
<string name="silent_mode_vibrate" msgid="7072043388581551395">"Vibračné zvonenie"</string>
@@ -160,11 +160,11 @@
<string name="no_recent_tasks" msgid="8794906658732193473">"Žiadne nedávne aplikácie"</string>
<string name="global_actions" product="tablet" msgid="408477140088053665">"Možnosti tabletu"</string>
<string name="global_actions" product="default" msgid="2406416831541615258">"Možnosti telefónu"</string>
- <string name="global_action_lock" msgid="2844945191792119712">"Uzamknutie obrazovky"</string>
+ <string name="global_action_lock" msgid="2844945191792119712">"Zámka obrazovky"</string>
<string name="global_action_power_off" msgid="4471879440839879722">"Vypnúť"</string>
- <string name="global_action_bug_report" msgid="7934010578922304799">"Správa o chybe"</string>
- <string name="bugreport_title" msgid="2667494803742548533">"Zaznamenať správu o chybe"</string>
- <string name="bugreport_message" msgid="398447048750350456">"Zhromažďuje informácie o aktuálnom stave zariadenia a tieto informácie je následne možné odoslať prostredníctvom e-mailovej správy. Od spustenia vytvárania správy o chybe až do chvíle, kedy je tento nástroj pripravený odoslať prvú správu, môže uplynúť nejaký čas. Prosíme vás preto o trpezlivosť."</string>
+ <string name="global_action_bug_report" msgid="7934010578922304799">"Hlásenie o chybách"</string>
+ <string name="bugreport_title" msgid="2667494803742548533">"Vytvoriť hlásenie o chybách"</string>
+ <string name="bugreport_message" msgid="398447048750350456">"Zhromaždí informácie o aktuálnom stave zariadenia na odoslanie v e-mailovej správe. Chvíľu však potrvá, kým bude hlásenie o chybách pripravené na odoslanie. Prosíme vás preto o trpezlivosť."</string>
<string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Tichý režim"</string>
<string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Zvuk je VYPNUTÝ."</string>
<string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Zvuk je zapnutý"</string>
@@ -233,7 +233,7 @@
<string name="permgrouplab_display" msgid="4279909676036402636">"Používateľské rozhranie iných aplikácií"</string>
<string name="permgroupdesc_display" msgid="6051002031933013714">"Vplyv na používateľské rozhranie ďalších aplikácií."</string>
<string name="permgrouplab_storage" msgid="1971118770546336966">"Úložisko"</string>
- <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Prístup do ukl. priestoru USB."</string>
+ <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Prístup do úložiska USB."</string>
<string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Prístup na kartu SD."</string>
<string name="permgrouplab_accessibilityFeatures" msgid="7919025602283593907">"Funkcie zjednodušenia ovládania"</string>
<string name="permgroupdesc_accessibilityFeatures" msgid="4205196881678144335">"Funkcie, ktoré môže vyžadovať nápomocná technológia."</string>
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Umožňuje aplikácii načítať obsah aktívneho okna. Škodlivé aplikácie môžu získať celý obsah okna a preskúmať celý jeho text okrem hesiel."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"dočasné povolenie zjednodušenia ovládania"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Umožňuje aplikácii dočasne povoliť zjednodušenie ovládania v zariadení. Škodlivé aplikáciu môžu zjednodušenie ovládania povoliť bez súhlasu používateľa."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"načítanie informácií o oknách"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Umožňuje aplikácii načítať informácie o oknách zo správcu okien. Škodlivé aplikácie môžu načítať informácie, ktoré sú určené pre interné využitie systému."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtrovanie udalostí"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Umožňuje aplikácii zaregistrovať vstupný filter, ktorý filtruje stream všetkých prenosov používateľa pred ich odvysielaním. Škodlivá aplikácia môže bez zásahu používateľa ovládať používateľské rozhranie systému."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"priblížiť zobrazenie"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Umožňuje aplikácii priblížiť obsah displeja. Škodlivé aplikácie môžu zmeniť zobrazenie obsahu tak, že sa zariadenie stane nepoužiteľným."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"Čiastočné vypnutie"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Uvedie správcu činností do vypnutého stavu. Úplné vypnutie však nenastane."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zabrániť prepínaniu aplikácií"</string>
@@ -351,7 +347,7 @@
<string name="permdesc_backup" msgid="6912230525140589891">"Umožňuje aplikácii ovládať mechanizmus na zálohovanie a obnovu údajov systému. Bežné aplikácie toto nastavenie nepoužívajú."</string>
<string name="permlab_confirm_full_backup" msgid="5557071325804469102">"potvrdenie operácie úplnej zálohy alebo úplného obnovenia"</string>
<string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"Umožňuje aplikácii spustiť používateľské rozhranie potvrdenia úplnej zálohy. Toto nastavenie by nemala používať žiadna aplikácia."</string>
- <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"zobrazenie neoprávnených okien"</string>
+ <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"zobraziť neoprávnené okná"</string>
<string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Umožňuje aplikácii vytvárať okná, ktoré majú byť použité interným systémom používateľského rozhrania. Bežné aplikácie toto nastavenie nepoužívajú."</string>
<string name="permlab_systemAlertWindow" msgid="3543347980839518613">"vykresliť cez ďalšie aplikácie"</string>
<string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Umožňuje aplikáciu vykresľovanie nad inými aplikáciami alebo súčasťami používateľského rozhrania. Táto funkcia môže zasahovať do vášho používania rozhrania inej aplikácie alebo meniť zobrazovaný obsah v iných aplikáciách."</string>
@@ -478,9 +474,9 @@
<string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Umožňuje aplikácii pristupovať k ďalším príkazom poskytovateľa informácií o polohe. Aplikácii to môže umožniť zasahovať do činnosti systému GPS alebo iných zdrojov informácií o polohe."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"Oprávnenie na inštaláciu poskytovateľa polohy"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Vytváranie simulovaných zdrojov polohy na testovanie alebo inštalácia nového poskytovateľa informácií o polohe. Aplikácii to umožní nahradiť polohu a stav, ktoré vracajú iné zdroje informácií o polohe, ako sú napríklad systém GPS alebo poskytovatelia informácií o polohe."</string>
- <string name="permlab_accessFineLocation" msgid="1191898061965273372">"presná poloha (pomocou GPS a siete)"</string>
+ <string name="permlab_accessFineLocation" msgid="1191898061965273372">"zistiť presnú polohu (pomocou GPS a siete)"</string>
<string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Umožňuje aplikácii získať vašu presnú polohu pomocou systému GPS (Global Positioning System) alebo zdrojov určenia polohy siete, napríklad mobilných veží a sietí Wi-Fi. Tieto služby určovania polohy musia byť na vašom zariadení zapnuté a dostupné, inak ich aplikácia nebude môcť využívať. Aplikácie môžu tieto služby využívať na určenie vašej polohy. Tieto služby môžu zvýšiť spotrebu batérie."</string>
- <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"približná poloha (pomocou siete)"</string>
+ <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"zistiť približnú polohu (pomocou siete)"</string>
<string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Umožňuje aplikácii získať vašu približnú polohu. Táto poloha je odvodená zo služieb určovania polohy pomocou zdrojov určenia polohy siete, napríklad mobilných veží a sietí Wi-Fi. Tieto služby určovania polohy musia byť na vašom zariadení zapnuté a dostupné, inak ich aplikácia nebude môcť využívať. Aplikácie môžu tieto služby využívať na určenie vašej približnej polohy."</string>
<string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"prístup k službe SurfaceFlinger"</string>
<string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Umožňuje aplikácii používať funkcie nízkej úrovne aplikácie SurfaceFlinger."</string>
@@ -502,13 +498,13 @@
<string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Umožňuje aplikácii zachytiť a presmerovať zabezpečený výstup videa."</string>
<string name="permlab_mediaContentControl" msgid="8749790560720562511">"ovládanie reprodukcie médií a prístup k metadátam"</string>
<string name="permdesc_mediaContentControl" msgid="1637478200272062">"Umožňuje aplikácii ovládať reprodukciu médií a pristupovať k informáciám o médiách (názov, autor...)."</string>
- <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"zmeny vašich nastavení zvuku"</string>
+ <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"meniť nastavenia zvuku"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Umožňuje aplikácii upraviť globálne nastavenia zvuku, ako je hlasitosť, alebo určiť, z ktorého reproduktora bude zvuk vychádzať."</string>
- <string name="permlab_recordAudio" msgid="3876049771427466323">"záznam zvuku"</string>
+ <string name="permlab_recordAudio" msgid="3876049771427466323">"nahrávať zvuk"</string>
<string name="permdesc_recordAudio" msgid="4906839301087980680">"Umožňuje aplikácii zaznamenávať zvuk pomocou mikrofónu. Toto povolenie umožňuje aplikácii zaznamenávať zvuk kedykoľvek bez vášho potvrdenia."</string>
<string name="permlab_sim_communication" msgid="1180265879464893029">"komunikácia s kartou SIM"</string>
<string name="permdesc_sim_communication" msgid="5725159654279639498">"Umožňuje aplikácii odosielať príkazy na kartu SIM. Toto je veľmi nebezpečné povolenie."</string>
- <string name="permlab_camera" msgid="3616391919559751192">"snímanie fotografií a natáčanie videí"</string>
+ <string name="permlab_camera" msgid="3616391919559751192">"fotiť a nakrúcať videá"</string>
<string name="permdesc_camera" msgid="8497216524735535009">"Umožňuje aplikácii fotografovať a nahrávať videá pomocou fotoaparátu. Toto povolenie umožňuje aplikácii používať fotoaparát kedykoľvek a bez vášho potvrdenia."</string>
<string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"Zakázať indikátor LED prenosu pri používaní fotoaparátu"</string>
<string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Umožňuje v predinštalovanej systémovej aplikácii zakázať indikátor LED používania fotoaparátu."</string>
@@ -538,7 +534,7 @@
<string name="permdesc_asec_rename" msgid="1794757588472127675">"Umožňuje aplikácii premenovať interné úložisko."</string>
<string name="permlab_vibrate" msgid="7696427026057705834">"ovládať vibrovanie"</string>
<string name="permdesc_vibrate" msgid="6284989245902300945">"Umožňuje aplikácii ovládať vibrácie."</string>
- <string name="permlab_flashlight" msgid="2155920810121984215">"ovládanie kontrolky"</string>
+ <string name="permlab_flashlight" msgid="2155920810121984215">"ovládať kontrolku"</string>
<string name="permdesc_flashlight" msgid="6522284794568368310">"Umožňuje aplikácii ovládať svetlo."</string>
<string name="permlab_manageUsb" msgid="1113453430645402723">"spravovať predvoľby a povolenia zariadení USB"</string>
<string name="permdesc_manageUsb" msgid="7776155430218239833">"Umožňuje aplikácii spravovať predvoľby a povolenia zariadení USB."</string>
@@ -566,7 +562,7 @@
<string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"čítanie presných stavov telefónu"</string>
<string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Umožňuje aplikácii pristupovať k presným stavom telefónu. Toto povolenie umožňuje aplikácii zistiť skutočný stav hovoru, či je hovor aktívny alebo na pozadí, zlyhania hovorov, presný stav dátového pripojenia a zlyhania dátového pripojenia."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zabránenie prechodu tabletu do režimu spánku"</string>
- <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"deaktivácia režimu spánku"</string>
+ <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"deaktivovať režim spánku"</string>
<string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Umožňuje aplikácii zabrániť prechodu tabletu do režimu spánku."</string>
<string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"Umožňuje aplikácii zabrániť prechodu telefónu do režimu spánku."</string>
<string name="permlab_transmitIr" msgid="7545858504238530105">"infračervený prenos"</string>
@@ -579,7 +575,7 @@
<string name="permlab_factoryTest" msgid="3715225492696416187">"spustenie v režime továrenského testu"</string>
<string name="permdesc_factoryTest" product="tablet" msgid="3952059318359653091">"Umožňuje aplikácii spustenie v režime nízkoúrovňového testu výrobcu a povolí úplný prístup k hardvéru tabletu. K dispozícii iba vtedy, keď je tablet spustený v režime testovania výrobcu."</string>
<string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Umožňuje aplikácii spustenie v režime nízkoúrovňového testu výrobcu a povolí úplný prístup k hardvéru telefónu. K dispozícii iba vtedy, keď je telefón spustený v režime testovania výrobcu."</string>
- <string name="permlab_setWallpaper" msgid="6627192333373465143">"nastavenie tapety"</string>
+ <string name="permlab_setWallpaper" msgid="6627192333373465143">"nastaviť tapetu"</string>
<string name="permdesc_setWallpaper" msgid="7373447920977624745">"Umožňuje aplikácii nastaviť tapetu systému."</string>
<string name="permlab_setWallpaperHints" msgid="3278608165977736538">"upraviť veľkosť tapety"</string>
<string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"Umožňuje aplikácii nastaviť tipy pre veľkosť tapety systému."</string>
@@ -614,7 +610,7 @@
<string name="permdesc_changeTetherState" msgid="1524441344412319780">"Umožňuje aplikácii zmeniť stav sieťového pripojenia zdieľaného pomocou tetheringu."</string>
<string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"zmeniť nastavenie použitia údajov na pozadí"</string>
<string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Umožňuje aplikácii zmeniť nastavenie používania údajov na pozadí."</string>
- <string name="permlab_accessWifiState" msgid="5202012949247040011">"zobraziť pripojenia siete Wi-Fi"</string>
+ <string name="permlab_accessWifiState" msgid="5202012949247040011">"zobraziť pripojenia Wi-Fi"</string>
<string name="permdesc_accessWifiState" msgid="5002798077387803726">"Umožňuje aplikácii zobraziť informácie o sieťach Wi-Fi. Napríklad o tom, či je sieť Wi-Fi povolená alebo názvy pripojených zariadení Wi-Fi."</string>
<string name="permlab_changeWifiState" msgid="6550641188749128035">"pripojiť a odpojiť od siete Wi-Fi"</string>
<string name="permdesc_changeWifiState" msgid="7137950297386127533">"Umožňuje aplikácii pripojiť sa na prístupové body siete Wi-Fi, odpojiť sa od nich a meniť konfiguráciu zariadení pre siete Wi-Fi."</string>
@@ -635,19 +631,19 @@
<string name="permlab_bluetooth" msgid="6127769336339276828">"párovať so zariadeniami Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Umožňuje aplikácii zobraziť informácie o konfigurácii Bluetooth na tablete. Taktiež jej umožňuje nadväzovať a akceptovať spojenia so spárovanými zariadeniami."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Umožňuje aplikácii zobraziť informácie o konfigurácii Bluetooth na telefóne. Taktiež jej umožňuje nadväzovať a akceptovať spojenia so spárovanými zariadeniami."</string>
- <string name="permlab_nfc" msgid="4423351274757876953">"ovládať technológiu Near Field Communication"</string>
- <string name="permdesc_nfc" msgid="7120611819401789907">"Umožňuje aplikácii komunikovať so značkami, kartami a čítačkami s podporou technológie Near Field Communication (NFC)."</string>
+ <string name="permlab_nfc" msgid="4423351274757876953">"ovládať technológiu NFC"</string>
+ <string name="permdesc_nfc" msgid="7120611819401789907">"Umožňuje aplikácii komunikovať so značkami, kartami a čítačkami s podporou technológie NFC."</string>
<string name="permlab_disableKeyguard" msgid="3598496301486439258">"deaktivácia zámky obrazovky"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Umožňuje aplikácii zakázať uzamknutie klávesnice a akékoľvek súvisiace zabezpečenie heslom. Príkladom je zakázanie uzamknutia klávesnice pri prichádzajúcom telefonickom hovore a jeho opätovné povolenie po skončení hovoru."</string>
- <string name="permlab_readSyncSettings" msgid="6201810008230503052">"čítanie nastavení synchronizácie"</string>
+ <string name="permlab_readSyncSettings" msgid="6201810008230503052">"čítať nastavenia synchronizácie"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Umožňuje aplikácii čítať nastavenia synchronizácie v účte. Môže napríklad určiť, či je s účtom synchronizovaná aplikácia Ľudia."</string>
- <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"prepínať nastavenie synchronizácie medzi hodnotou zapnuté a vypnuté"</string>
+ <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"zapnúť alebo vypnúť synchronizáciu"</string>
<string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Umožňuje aplikácii upraviť nastavenia synchronizácie v účte. Pomocou tohto povolenia je možné napríklad povoliť synchronizáciu aplikácie Ľudia s účtom."</string>
<string name="permlab_readSyncStats" msgid="7396577451360202448">"čítanie štatistických údajov o synchronizácii"</string>
<string name="permdesc_readSyncStats" msgid="1510143761757606156">"Umožňuje aplikácii čítať štatistické informácie o synchronizácii v účte vrátane histórie uskutočnených synchronizácií a informácií o množstve synchronizovaných údajov."</string>
- <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"čítanie zdrojov prihlásených na odber"</string>
+ <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"čítať odoberané informačné kanály"</string>
<string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Umožňuje aplikácii získať podrobnosti o aktuálne synchronizovaných informačných kanáloch."</string>
- <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"zápis odoberaných zdrojov"</string>
+ <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"zapisovať odoberané informačné kanály"</string>
<string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Umožňuje aplikácii upraviť vaše aktuálne synchronizované informačné kanály. Škodlivé aplikácie môžu synchronizované informačné kanály zmeniť."</string>
<string name="permlab_readDictionary" msgid="4107101525746035718">"čítať výrazy pridané do slovníka"</string>
<string name="permdesc_readDictionary" msgid="659614600338904243">"Umožňuje aplikácii čítať všetky slová, názvy a frázy, ktoré mohol používateľ uložiť do svojho slovníka."</string>
@@ -705,7 +701,7 @@
<string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Bez predchádzajúceho upozornenia zmazať všetky údaje tým, že sa obnovia továrenské nastavenia telefónu."</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Nastaviť globálny server proxy zariadenia"</string>
<string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Vyberte globálny server proxy, ktorý sa bude používať po aktivácii pravidiel. Platný globálny server proxy nastavuje iba prvý správca zariadenia."</string>
- <string name="policylab_expirePassword" msgid="885279151847254056">"Nastav. koniec platnosti hesla"</string>
+ <string name="policylab_expirePassword" msgid="885279151847254056">"Nastaviť vypršanie hesla zámky"</string>
<string name="policydesc_expirePassword" msgid="1729725226314691591">"Nastavte, ako často sa musí zmeniť heslo na uzamknutie obrazovky."</string>
<string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nastaviť šifr. ukl. priestoru"</string>
<string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Vyžadovať šifrovanie uložených údajov aplikácií."</string>
@@ -1148,7 +1144,7 @@
<string name="anr_application_process" msgid="8941757607340481057">"Aplikácia <xliff:g id="APPLICATION">%1$s</xliff:g> neodpovedá. Chcete ju zavrieť?"</string>
<string name="anr_process" msgid="6513209874880517125">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> neodpovedá. \n\nChcete ho zavrieť?"</string>
<string name="force_close" msgid="8346072094521265605">"OK"</string>
- <string name="report" msgid="4060218260984795706">"Prehľad"</string>
+ <string name="report" msgid="4060218260984795706">"Nahlásiť"</string>
<string name="wait" msgid="7147118217226317732">"Čakajte"</string>
<string name="webpage_unresponsive" msgid="3272758351138122503">"Stránka nereaguje.\n\nChcete ju zavrieť?"</string>
<string name="launch_warning_title" msgid="1547997780506713581">"Presmerovaná aplikácia"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index cab43f2..1302eb8 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Programu omogoča dostop do vsebine aktivnega okna. Zlonamerni programi lahko dobijo vso vsebino okna in pregledajo njeno besedilo razen gesel."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"začasno omogoči pripomočke za ljudi s posebnimi potrebami"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Aplikaciji omogoča, da v napravi začasno omogoči pripomočke za ljudi s posebnimi potrebami. Zlonamerne aplikacije jih lahko omogočijo brez soglasja uporabnika."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"prenos podatkov o oknih"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Omogoča, da aplikacija iz upravitelja oken pridobiva podatke o oknih. Zlonamerne aplikacije lahko pridobivajo podatke, namenjene za notranjo uporabo v sistemu."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtriranje dogodkov"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Omogoča, da aplikacija registrira vhodni filter, ki pred razpošiljanjem filtrira tok vseh uporabniških dogodkov. Zlonamerne aplikacije lahko nadzirajo uporabniški vmesnik sistema brez posega uporabnika."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"povečevanje zaslona"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Omogoča aplikaciji povečevanje vsebine zaslona. Zlonamerne aplikacije lahko preoblikujejo vsebino zaslona tako, da je naprava neuporabna."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"delna zaustavitev"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Upravitelja dejavnosti preklopi v stanje za zaustavitev. Ne izvede celotne zaustavitve."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"preprečevanje preklopa programov"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 7895ded..e636874 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Дозвољава апликацији да преузме садржај активног прозора. Злонамерне апликације могу да преузму цео садржај прозора и прегледају целокупан текст, осим лозинки."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"привремено омогућавање приступачности"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Дозвољава апликацији да привремено омогући приступачност на уређају. Злонамерне апликације могу да омогуће приступачност без дозволе корисника."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"преузимање информација о прозорима"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Омогућава апликацији да преузме информације о прозорима од менаџера прозора. Злонамерне апликације могу да преузму информације које су намењене за интерну употребу система."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"филтрирање догађаја"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Омогућава апликацији да региструје филтер улазног садржаја који филтрира стрим свих догађаја корисника пре њиховог слања. Злонамерна апликација може да контролише кориснички интерфејс система без интервенције корисника."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"увеличавање екрана"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Дозвољава апликацији да увеличава садржај екрана. Злонамерне апликације могу да промене садржај екрана до те мере да уређај постаје неупотребљив."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"делимично искључивање"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Ставља менаџера активности у стање искључивања. Не искључује га у потпуности."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"спречавање пребацивања са једне апликације на другу"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index c29f0a3..31e3c9c 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Tillåter att appen hämtar innehållet i det aktiva fönstret. Skadliga appar kan hämta allt innehåll i fönstret och läsa all text utom lösenord."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"aktivera tillgänglighetsläget tillfälligt"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Tillåt att en app tillfälligt aktiverar tillgänglighetsläget på enheten. Skadliga appar kan aktivera tillgänglighetsläget utan användarens medgivande."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"hämta information om fönster"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Tillåter att appen hämtar information om fönstren från fönsterhanteraren. Skadliga appar kan hämta information som är avsedd för användning i det interna systemet."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"filtrera händelser"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Tillåter att appen registrerar indatafilter som filtrerar flödet med användarhändelser innan de skickas. Skadliga appar kan styra systemets användargränssnitt utan att användaren gör något."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"förstora skärmen"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Tillåter att en app förstorar innehållet på en skärm. Skadliga appar kan förvandla skärminnehållet på ett sätt som gör att enheten blir oanvändbar."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"avsluta delvis"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Sätter aktivitetshanteraren i avstängningsläge. Utför inte en fullständig avstängning."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"förhindrar programbyten"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 3e11aa1..84fbf08 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Inaruhusu programu kutoa maudhui ya dirisha amilifu. Programu hasidi zinaweza kutoa maudhui yote ya dirisha na kuchunguza maandishi yake yote isipokuwa nenosiri."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"wezesha ufikivu kwa muda"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Inaruhusu programu kuwezesha kwa muda ufikivu kwenye kifaa. Huenda programu hasidi zikawezesha ufikivu bila kibali cha mtumiaji."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"okoa maelezo ya dirisha"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Huruhusu programu kuokoa maelezo kuhusu madirisha kutoka kwenye kidhibiti dirisha. Huenda programu hasidi ikakusanya maelezo ambayo yamekusudiwa kwa matumizi ya mfumo wa ndani."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"chuja matukio"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Huruhusu programu kusajili kichujio ingizo kinachochuja mkondo wa matukio ya mtumiaji kabla ya kutumwa. Huenda programu hasidi ikadhibiti mfumo wa UI bila mtumiaji kuingilia kati."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"kuza oneysho"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Inaruhusu programu kukuza maudhui ya onyesho. Programu hasidi zinaweza kubadili maudhui kwa njia ambayo inaweza kukifanya kifaa kutotumika."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"Zima nusu"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Huweka kisimamia shughuli katika hali ya kuzima. Haiadhiri uzimaji kamili"</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zuia swichi za app"</string>
@@ -536,7 +532,7 @@
<string name="permdesc_asec_mount_unmount" msgid="3451360114902490929">"Inaruhusu programu kupachika/kupachua hifadhi ya ndani."</string>
<string name="permlab_asec_rename" msgid="7496633954080472417">"ipe hifadhi ya ndani jina jipya"</string>
<string name="permdesc_asec_rename" msgid="1794757588472127675">"Inaruhusu programu kubadilisha jina la hifadhi ya ndani."</string>
- <string name="permlab_vibrate" msgid="7696427026057705834">"dhibiti mtetemo"</string>
+ <string name="permlab_vibrate" msgid="7696427026057705834">"Kudhibiti mtetemo"</string>
<string name="permdesc_vibrate" msgid="6284989245902300945">"Inaruhusu programu kudhibiti kitingishi."</string>
<string name="permlab_flashlight" msgid="2155920810121984215">"dhibiti tochi"</string>
<string name="permdesc_flashlight" msgid="6522284794568368310">"Inaruhusu programu kudhibiti tochi."</string>
@@ -614,7 +610,7 @@
<string name="permdesc_changeTetherState" msgid="1524441344412319780">"Inaruhusu programu kubadilisha hali ya muunganisho wa mtandao uliofungwa."</string>
<string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"badilisha mpangilio wa utumiaji data ya mandharinyuma"</string>
<string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Inaruhusu programu kubadilisha mpangilio wa matumizi ya data ya usuli."</string>
- <string name="permlab_accessWifiState" msgid="5202012949247040011">"ona miunganisho ya Wi-Fi"</string>
+ <string name="permlab_accessWifiState" msgid="5202012949247040011">"Kuona miunganisho ya Wi-Fi"</string>
<string name="permdesc_accessWifiState" msgid="5002798077387803726">"Inaruhusu programu kuona taarifa kuhusu mtandao wa Wi-Fi, kama vile ikiwa Wi-Fi imewezeshwa mna jina la vifaa vya Wi-Fi vilivyounganishwa."</string>
<string name="permlab_changeWifiState" msgid="6550641188749128035">"unganisha na utenganishe kutoka kwa Wi-Fi"</string>
<string name="permdesc_changeWifiState" msgid="7137950297386127533">"Inaruhusu programu kuunganisha kwenye au kukata kutoka pointi za ufikivu wa Wi-Fi na kufanya mabadiliko kwenye usanidi wa kifaa cha mitandao ya Wi-Fi."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 305036d..57850a1 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"อนุญาตให้แอปพลิเคชันดึงเนื้อหาของหน้าต่างที่ใช้งานอยู่ แอปพลิเคชันที่เป็นอันตรายอาจดึงเนื้อหาจากหน้าต่างทั้งหมดและตรวจสอบข้อความทั้งหมดยกเว้นรหัสผ่าน"</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"เปิดใช้งานการเข้าถึงชั่วคราว"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"ช่วยให้แอปพลิเคชันสามารถเปิดใช้งานการเข้าถึงบนอุปกรณ์เป็นการชั่วคราว แอปพลิเคชันที่เป็นอันตรายอาจเปิดใช้งานการเข้าถึงโดยไม่ได้รับความยินยอมจากผู้ใช้"</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"เรียกข้อมูลหน้าต่าง"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"อนุญาตให้แอปพลิเคชันดึงข้อมูลเกี่ยวกับหน้าต่างจากเครื่องมือจัดการหน้าต่าง แอปพลิเคชันที่เป็นอันตรายอาจดึงข้อมูลที่มีไว้เพื่อการใช้ของระบบภายใน"</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"กรองกิจกรรม"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"อนุญาตให้แอปพลิเคชันลงทะเบียนตัวกรองข้อมูลซึ่งจะกรองสตรีมกิจกรรมทั้งหมดของผู้ใช้ก่อนที่จะทำการเผยแพร่ออกไป แอปพลิเคชันที่เป็นอันตรายอาจควบคุม UI ของระบบโดยไม่ต้องให้ผู้ใช้จัดการ"</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"ขยายการแสดงผล"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"อนุญาตให้แอปพลิเคชันขยายเนื้อหาที่แสดงผล แอปพลิเคชันที่เป็นอันตรายอาจแปลงเนื้อหาที่แสดงในลักษณะที่ทำให้ไม่สามารถใช้อุปกรณ์ได้"</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"ปิดการทำงานบางส่วน"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"กำหนดให้ตัวจัดการกิจกรรมอยู่ในสถานะปิดระบบ โดยไม่ได้ปิดระบบอย่างสมบูรณ์"</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ป้องกันการเปลี่ยนแอปพลิเคชัน"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index ec73999..b91b44c 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Pinapayagan ang app na bawiin ang nilalaman ng aktibong window. Maaaring bawiin ng nakakahamak na apps ang kabuuang nilalaman ng window at suriin ang lahat ng teksto nito maliban sa mga password."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"pansamantalang paganahin ang accessibility"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Nagbibigay-daan sa isang application na pansamantalang paganahin ang accessibility sa device. Maaaring paganahin ng nakakahamak na apps ang accessibility nang walang pahintulot ng user."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"kunin ang impormasyon ng window"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Pinapayagan ang application na kumuha ng impormasyon tungkol sa mga window mula sa tagapamahala ng window. Maaaring kumuha ang mga nakakahamak na app ng impormasyong nilayon para sa panloob na paggamit ng system."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"i-filter ang mga kaganapan"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Pinapayagan ang isang application na magrehistro ng filter ng input na nagpi-filter sa stream ng lahat ng kaganapan ng user bago maipadala ang mga iyon. Maaaring kontrolin ng nakakahamak na app ang system UI nang hindi nakikialam ang user."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"i-magnify ang display"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Pinapayagan ang isang application na i-magnify ang nilalaman ng isang display. Maaaring ibahin ng nakakahamak na apps ang nilalaman ng display sa paraang nagre-render sa device na hindi kapaki-pakinabang."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"bahagyang pag-shutdown"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Inilalagay ang tagapamahala ng aktibidad sa katayuan ng pag-shutdown. Hindi nagsasagawa ng kumpletong pag-shutdown."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"pigilan ang mga paglipat ng app"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 902939e..dfb21f7 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Uygulamaya, etkin pencerenin içeriğini alma izni verir. Kötü amaçlı uygulamalar tüm pencere içeriğini alabilir ve şifreleri hariç tüm metni inceleyebilir."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"erişilebilirliği geçici olarak etkinleştir"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Uygulamaya, cihazda erişilebilirliği geçici olarak etkinleştirme izni verir. Kötü amaçlı uygulamalar, kullanıcının izni olmadan erişilebilirliği etkinleştirebilirler."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"pencere bilgilerini al"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Uygulamaya, pencere yöneticisinden pencerelerle ilgili bilgi alma izni verir. Zararlı uygulamalar dahili sistem kullanımına yönelik bilgileri alabilir."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"etkinlikleri filtrele"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Uygulamaya, tüm kullanıcı etkinlikleri dağıtılmadan önce ilgili akışa filtre uygulayan bir giriş filtresi kaydetme izni verir. Zararlı uygulamalar kullanıcı müdahalesi olmadan sistem arayüzünü denetleyebilir."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"ekranı büyüt"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Uygulamaya bir ekranın içeriğini büyütme izni verir. Kötü amaçlı uygulamalar ekranın içeriğini etkileyerek cihazı kullanılmaz hale getirebilir."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"kısmi kapatma"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Eylem yöneticisini kapalı duruma getirir. Tam kapatma işlemi gerçekleştirmez."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"uygulama değişimlerini engelle"</string>
@@ -653,7 +649,7 @@
<string name="permdesc_readDictionary" msgid="659614600338904243">"Uygulamaya, kullanıcının kullanıcı sözlüğünde depolamış olabileceği kelimeleri, adları ve kelime öbeklerini okuma izni verir."</string>
<string name="permlab_writeDictionary" msgid="2183110402314441106">"kullanıcı tanımlı sözlüğe kelime ekle"</string>
<string name="permdesc_writeDictionary" msgid="8185385716255065291">"Uygulamaya, kullanıcı sözlüğüne yeni kelimeler yazma izni verir."</string>
- <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"USB belleğimin içeriğini oku"</string>
+ <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"USB belleğini okuma"</string>
<string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"SD kartımın içeriğini oku"</string>
<string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"Uygulamaya, USB depolama biriminizin içeriğini okuma izni verir."</string>
<string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"Uygulamaya, SD kartınızın içeriğini okuma izni verir."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index fb96ca0..238293c 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -136,7 +136,7 @@
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Забагато видалень <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Пам’ять планшетного ПК заповнено. Видаліть якісь файли, щоб звільнити місце."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Пам’ять телефону заповнено. Видаліть якісь файли, щоб звільнити місце."</string>
- <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Мережу можуть відстежувати"</string>
+ <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Мережа може відстежуватися"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Невідомою третьою стороною"</string>
<string name="ssl_ca_cert_noti_managed" msgid="4030263497686867141">"Доменом <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string>
<string name="me" msgid="6545696007631404292">"Я"</string>
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Дозволяє програмі отримувати вміст активного вікна. Шкідливі програми можуть отримувати весь вміст вікна та вивчати весь його текст, окрім паролів."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"тимчасово вмикати доступність"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Дозволяє програмі тимчасового вмикати доступність на пристрої. Шкідливі програми можуть вмикати доступність без згоди користувача."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"отримувати інформацію про вікна"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Дозволяє програмі отримувати інформацію про вікна від диспетчера вікон. Шкідливі програми можуть отримувати інформацію, яка призначена для внутрішнього користування системи."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"фільтрувати події"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Дозволяє програмі реєструвати вхідний фільтр, який фільтрує потік усіх подій користувача перед їх надсиланням. Шкідливі програми можуть контролювати інтерфейс системи без втручання користувача."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"збільшити екран"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Дозволяє програмі збільшувати вміст екрана. Зловмисні програми можуть змінювати вміст екрана так, що пристроєм стає неможливо користуватися."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"частк. заверш. роб."</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Переводить диспетчер дій у стан завершення роботи. Не виконує повне завершення роботи."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"запобіг. зміні програм"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 60b97c3..b0a617f 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Cho phép ứng dụng truy xuất nội dung của cửa sổ hiện hành. Ứng dụng độc hại có thể truy xuất toàn bộ nội dung của cửa sổ cũng như xem xét toàn bộ văn bản của cửa sổ ngoại trừ mật khẩu."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"tạm thời bật trợ năng"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Cho phép ứng dụng tạm thời bật trợ năng trên thiết bị. Các ứng dụng độc hại có thể bật trợ năng mà không có sự đồng ý của người dùng."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"truy xuất thông tin cửa sổ"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Cho phép ứng dụng truy xuất thông tin về các cửa sổ từ trình quản lý cửa sổ. Các ứng dụng độc hại có thể truy xuất thông tin được dành để sử dụng trong hệ thống nội bộ."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"lọc sự kiện"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Cho phép ứng dụng đăng ký bộ lọc dữ liệu nhập để lọc luồng tất cả các sự kiện người dùng trước khi chúng được gửi đi. Ứng dụng độc hại có thể kiểm soát Giao diện người dùng hệ thống mà không cần sự can thiệp của người dùng."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"thu phóng màn hình"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Cho phép ứng dụng thu phóng nội dung trên màn hình. Ứng dụng độc hại có thể biến đổi nội dung trên màn hình theo cách kết xuất thiết bị không thể sử dụng được."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"tắt từng phần"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Đặt trình quản lý hoạt động sang trạng thái tắt. Không thực hiện tắt hoàn toàn."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ngăn chuyển đổi ứng dụng"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 1b775e8..902533a 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -170,7 +170,7 @@
<string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"声音已开启"</string>
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"飞行模式"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"已开启飞行模式"</string>
- <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"已关闭飞行模式"</string>
+ <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"未开启飞行模式"</string>
<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>
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"允许应用检索活动窗口的内容。恶意应用可能会检索整个窗口的内容,并检查其中除密码以外的所有文字。"</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"暂时启用辅助功能"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"允许应用在设备上暂时启用辅助功能。恶意应用可能会在未经用户同意的情况下擅自启用辅助功能。"</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"检索窗口信息"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"允许应用通过窗口管理器检索窗口信息。恶意应用可能会检索供内部系统使用的信息。"</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"过滤事件"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"允许应用注册输入过滤器,这类过滤器会在所有用户事件分派之前对用户事件流进行过滤。恶意应用可能会在没有用户干预的情况下控制系统用户界面。"</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"放大显示内容"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"允许应用放大显示内容。恶意应用可能会以特定方式改变显示内容,使得设备无法使用。"</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"部分关机"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"使活动管理器进入关闭状态。不执行彻底关机。"</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"禁止切换应用"</string>
@@ -479,9 +475,9 @@
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"允许安装位置信息提供程序"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"创建用于测试的模拟位置源或安装新的位置提供程序。此权限可让该应用覆盖由其他位置源(如 GPS)或位置提供程序返回的位置和/或状态信息。"</string>
<string name="permlab_accessFineLocation" msgid="1191898061965273372">"精确位置(基于 GPS 和网络)"</string>
- <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"允许该应用通过全球定位系统 (GPS) 或网络位置信息源(例如基站和 WLAN)获取您的精确位置信息。您必须在设备上开启这些位置服务,应用才能获得位置信息。应用会使用此类服务确定您的位置,这可能会消耗更多电量。"</string>
+ <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"允许该应用通过全球定位系统(GPS)或网络位置信息源(例如基站和WLAN)获取您的精确位置信息。您必须在设备上开启这些位置信息服务,应用才能获得位置信息。应用会使用此类服务确定您的位置,这可能会消耗更多电量。"</string>
<string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"大致位置(基于网络)"</string>
- <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"允许该应用获取您的大致位置信息。这类位置信息来自于使用网络位置信息源(例如基站和 WLAN)的位置服务。您必须在设备上开启这些位置服务,应用才能获得位置信息。应用会使用此类服务确定您的大概位置。"</string>
+ <string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"允许该应用获取您的大致位置信息。这类位置信息来自于使用网络位置信息源(例如基站和WLAN)的位置信息服务。您必须在设备上开启这些位置信息服务,应用才能获得位置信息。应用会使用此类服务确定您的大概位置。"</string>
<string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"访问 SurfaceFlinger"</string>
<string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"允许应用使用 SurfaceFlinger 低级功能。"</string>
<string name="permlab_readFrameBuffer" msgid="6690504248178498136">"读取帧缓冲区"</string>
@@ -1130,7 +1126,7 @@
<string name="no" msgid="5141531044935541497">"取消"</string>
<string name="dialog_alert_title" msgid="2049658708609043103">"注意"</string>
<string name="loading" msgid="7933681260296021180">"正在加载..."</string>
- <string name="capital_on" msgid="1544682755514494298">"打开"</string>
+ <string name="capital_on" msgid="1544682755514494298">"开启"</string>
<string name="capital_off" msgid="6815870386972805832">"关闭"</string>
<string name="whichApplication" msgid="4533185947064773386">"选择要使用的应用:"</string>
<string name="whichHomeApplication" msgid="4616420172727326782">"选择主屏幕应用"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 1273200..d189060 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"允許應用程式擷取使用中的視窗內容。惡意應用程式可能會擷取整個視窗的內容,以及檢視密碼除外的所有文字。"</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"暫時啟用協助工具"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"允許應用程式在裝置上暫時啟用協助工具。惡意應用程式可能藉此在未經用戶同意的情況下擅自啟用協助工具。"</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"擷取視窗資訊"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"允許應用程式從視窗管理程式擷取視窗的相關資訊。惡意應用程式可能會擷取專供內部系統使用的資訊。"</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"篩選活動"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"允許應用程式註冊輸入篩選器,在分派所有用戶活動的串流前先行篩選。惡意應用程式可能會繞過用戶操作,直接控制系統用戶介面。"</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"放大畫面"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"允許應用程式放大畫面內容。惡意應用程式可能會改變顯示內容,導致裝置失靈。"</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"部分關機"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"讓活動管理員進入關機狀態,而不執行完整的關機程序。"</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"防止切換應用程式"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index f4b96d0..dcdfd28 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"允許應用程式擷取使用中的視窗內容。請注意,惡意應用程式可能利用此功能擷取完整視窗內容,並檢視密碼之外的所有文字。"</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"暫時啟用協助工具"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"允許應用程式在裝置上暫時啟用協助工具。惡意應用程式可能藉此在未經使用者同意的情況下擅自啟用協助工具。"</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"擷取視窗資訊"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"允許應用程式透過視窗管理程式擷取視窗的相關資訊。請注意,惡意應用程式可能藉此擷取僅限內部系統使用的資訊。"</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"篩選活動"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"允許應用程式註冊輸入篩選器,在分派所有使用者活動的串流前先行篩選。請注意,惡意應用程式可能藉此擅自控制系統使用者介面。"</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"放大畫面"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"允許應用程式放大畫面內容。請注意,惡意應用程式可能會藉此利用不正常的方式改變顯示內容,導致裝置失靈。"</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"部分關機"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"讓活動管理員進入關機狀態,而不執行完整的關機程序。"</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"防止切換應用程式"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index c7faf48..1b12907 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -315,12 +315,8 @@
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Ivumela uhlelo lokusebenza ukuthi ithole okuqukethe kwi-Window. Izuhlelo lokusebenza ezinobungozi zingathola kabush iwindi eliphelele bese ibheka konke okuqukethwe ngaphandle kwaaaphasiwedi."</string>
<string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"nika amandla okwesikhashana ukufinyelela"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Ivumela uhlelo lokusebenza ukunika amandla ukufinyelela kwesikhashana kuvidayisi. Izinhlelo zokusebenza ezingalungile zinganika amandla ukufinyelela ngaphandle kwemvume yomsebenzisi."</string>
- <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"buyisa ulwazi lewindi"</string>
- <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Ivumela uhlelo lokusebenza ukubuyisa ulwazi mayelana namawindi avela kumphathi wewindi. Izinhlelo zokusebenza zingabuyisa ulwazi olubhekiswe ukusetshenziselwa kohlelo lwangaphakathi."</string>
<string name="permlab_filter_events" msgid="8675535648807427389">"hlunga imicimbi"</string>
<string name="permdesc_filter_events" msgid="8006236315888347680">"Ivumela uhlelo lokusebenza ukubhalisa isihlungi sokufaka ukusakaza kwazo zonke izehlakalo zomsebenzisi ngaphambi kokuthunyelwa. Izinhlelo zokusebenza zingalawula i-UI yohlelo ngaphandle kokungena komsebenzisi."</string>
- <string name="permlab_magnify_display" msgid="5973626738170618775">"lungisa ukubuka"</string>
- <string name="permdesc_magnify_display" msgid="7121235684515003792">"Ivumela uhlelo lokusebenza ukusondeza okuqukethwe kokubukwa. Izinhlelo zokusebenza ezingalungile zidlulisela okuqukethwe kokubuka ngendlela eyenza idivayisi ingasebenziseki."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"ukuvala shaqa kwengxenye"</string>
<string name="permdesc_shutdown" msgid="7046500838746291775">"Ibeka imeneja yomsebenzi kwisimo sokuvala shaqa. Ayenzi ukuvala shaqa okuphelele."</string>
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"gwema ukushintsha kohlelo lokusebenza"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 4d272ee..aa5005f 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -677,8 +677,6 @@
<!-- Action bar styles -->
<!-- =================== -->
<eat-comment />
- <!-- Theme override for the Action Bar -->
- <attr name="actionBarTheme" format="reference" />
<!-- Default style for tabs within an action bar -->
<attr name="actionBarTabStyle" format="reference" />
<attr name="actionBarTabBarStyle" format="reference" />
@@ -910,6 +908,16 @@
<!-- Drawable for WebView find-on-page dialogue's "previous" button. @hide -->
<attr name="findOnPagePreviousDrawable" format="reference" />
+ <!-- ============= -->
+ <!-- Color palette -->
+ <!-- ============= -->
+ <attr name="colorControlNormal" format="color" />
+ <attr name="colorControlActivated" format="color" />
+ <attr name="colorButtonNormal" format="color" />
+ <attr name="colorButtonPressed" format="color" />
+ <attr name="colorButtonNormalColored" format="color" />
+ <attr name="colorButtonPressedColored" format="color" />
+
</declare-styleable>
<!-- **************************************************************** -->
@@ -1667,6 +1675,7 @@
that is, when in portrait. Can be either an absolute dimension
or a fraction of the screen size in that dimension. -->
<attr name="windowFixedHeightMajor" format="dimension|fraction" />
+ <attr name="windowOutsetBottom" format="dimension" />
</declare-styleable>
<!-- The set of attributes that describe a AlertDialog's theme. -->
@@ -4426,16 +4435,12 @@
<!-- Drawable used to show animated touch feedback. -->
<declare-styleable name="TouchFeedbackDrawable">
- <!-- The tint to use for feedback ripples. This attribute is mandatory. -->
+ <!-- The tint to use for feedback ripples. This attribute is required. -->
<attr name="tint" />
<!-- Specifies the Porter-Duff blending mode used to apply the tint. The default vlaue is src_atop, which draws over the opaque parts of the drawable. -->
<attr name="tintMode" />
<!-- Whether to pin feedback ripples to the center of the drawable. Default value is false. -->
<attr name="pinned" format="boolean" />
- <!-- Optional drawable used to mask ripple bounds before projection. -->
- <attr name="mask" format="reference" />
- <!-- Optional drawable onto which ripples are projected. -->
- <attr name="drawable" />
</declare-styleable>
<declare-styleable name="ScaleDrawable">
@@ -4531,6 +4536,146 @@
</declare-styleable>
<!-- ========================== -->
+ <!-- Vector drawable class -->
+ <!-- ========================== -->
+ <eat-comment />
+
+ <!-- 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>
+
+ <!-- Define the virtual size of the drawing surface paths will draw to. -->
+ <declare-styleable name="VectorDrawableViewport">
+ <!-- The width of the canvas the drawing is on. -->
+ <attr name="viewportWidth" format="float"/>
+ <!-- The height of the canvas the drawing is on. -->
+ <attr name="viewportHeight" format="float"/>
+ </declare-styleable>
+
+ <!-- Define the size of the drawable -->
+ <declare-styleable name="VectorDrawableSize">
+ <!-- Width of the Vector Drawable. -->
+ <attr name="width" />
+ <!-- Height of the Vector Drawable. -->
+ <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 -->
+ <attr name="name" />
+ <!-- The width a path stroke -->
+ <attr name="strokeWidth" format="float" />
+ <!-- The opacity of a path stroke -->
+ <attr name="strokeOpacity" format="float" />
+ <!-- The amount to rotate the path stroke -->
+ <attr name="rotation" />
+ <!-- The X coordinate of the center of rotation of a path -->
+ <attr name="pivotX" />
+ <!-- The Y coordinate of the center of rotation of a path -->
+ <attr name="pivotY" />
+ <!-- The color to stroke the path if not defined implies no stroke-->
+ <attr name="stroke" format="color" />
+ <!-- The color to fill the path if not defined implies no fill-->
+ <attr name="fill" format="color" />
+ <!-- The level of opacity of the filled area of the path -->
+ <attr name="fillOpacity" format="float" />
+ <!-- The specification of the operations that define the path -->
+ <attr name="pathData" format="string" />
+ <!-- The fraction of the path to trim from the start from 0 to 1 -->
+ <attr name="trimPathStart" format="float" />
+ <!-- The fraction of the path to trim from the end from 0 to 1 -->
+ <attr name="trimPathEnd" format="float" />
+ <!-- Shift trim region (allows visible region to include the start and end) from 0 to 1 -->
+ <attr name="trimPathOffset" format="float" />
+ <!-- Path will set the current clip path -->
+ <attr name="clipToPath" format="boolean" />
+ <!-- sets the linecap for a stroked path -->
+ <attr name="strokeLineCap" format="enum">
+ <enum name="butt" value="0"/>
+ <enum name="round" value="1"/>
+ <enum name="square" value="2"/>
+ </attr>
+ <!-- sets the lineJoin for a stroked path -->
+ <attr name="strokeLineJoin" format="enum">
+ <enum name="miter" value="0"/>
+ <enum name="round" value="1"/>
+ <enum name="bevel" value="2"/>
+ </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>
+
+ <!-- ========================== -->
<!-- Animation class attributes -->
<!-- ========================== -->
<eat-comment />
@@ -5780,6 +5925,16 @@
<attr name="settingsActivity" />
</declare-styleable>
+ <!-- Use <code>trust_agent</code> as the root tag of the XML resource that
+ describes an {@link android.service.trust.TrustAgentService}, which is
+ referenced from its {@link android.service.trust.TrustAgentService#TRUST_AGENT_META_DATA}
+ meta-data entry. Described here are the attributes that can be included in that tag. -->
+ <declare-styleable name="TrustAgent">
+ <!-- Component name of an activity that allows the user to modify
+ the settings for this TrustAgent. -->
+ <attr name="settingsActivity" />
+ </declare-styleable>
+
<!-- =============================== -->
<!-- Accounts package class attributes -->
<!-- =============================== -->
@@ -5888,16 +6043,16 @@
<eat-comment />
<declare-styleable name="GlowPadView">
<!-- Reference to an array resource that be shown as targets around a circle. -->
- <attr name="targetDrawables"/>
+ <attr name="targetDrawables" format="reference" />
<!-- Reference to an array resource that be used as description for the targets around the circle. -->
- <attr name="targetDescriptions"/>
+ <attr name="targetDescriptions" format="reference" />
<!-- Reference to an array resource that be used to announce the directions with targets around the circle. -->
- <attr name="directionDescriptions"/>
+ <attr name="directionDescriptions" format="reference" />
<!-- Sets a drawable as the center. -->
- <attr name="handleDrawable"/>
+ <attr name="handleDrawable" format="reference" />
<!-- Drawable to use for wave ripple animation. -->
<attr name="outerRingDrawable" format="reference"/>
@@ -5909,22 +6064,22 @@
<attr name="innerRadius"/>
<!-- Outer radius of glow area. Target icons will be drawn on this circle. -->
- <attr name="outerRadius"/>
+ <attr name="outerRadius" format="dimension" />
<!-- Radius of glow under finger. -->
<attr name="glowRadius" format="dimension" />
<!-- Tactile feedback duration for actions. Set to '0' for no vibration. -->
- <attr name="vibrationDuration"/>
+ <attr name="vibrationDuration" format="integer" />
<!-- How close we need to be before snapping to a target. -->
- <attr name="snapMargin"/>
+ <attr name="snapMargin" format="dimension" />
<!-- Number of waves/chevrons to show in animation. -->
- <attr name="feedbackCount"/>
+ <attr name="feedbackCount" format="integer" />
<!-- Used when the handle shouldn't wait to be hit before following the finger -->
- <attr name="alwaysTrackFinger"/>
+ <attr name="alwaysTrackFinger" format="boolean" />
<!-- Location along the circle of the first item, in degrees.-->
<attr name="firstItemOffset" format="float" />
@@ -5941,45 +6096,6 @@
</declare-styleable>
<!-- =============================== -->
- <!-- MultiWaveView class attributes -->
- <!-- =============================== -->
- <eat-comment />
- <declare-styleable name="MultiWaveView">
- <!-- Reference to an array resource that be shown as targets around a circle. -->
- <attr name="targetDrawables" format="reference"/>
-
- <!-- Reference to an array resource that be used as description for the targets around the circle. -->
- <attr name="targetDescriptions" format="reference"/>
-
- <!-- Reference to an array resource that be used to announce the directions with targets around the circle. -->
- <attr name="directionDescriptions" format="reference"/>
-
- <!-- Sets a drawable as the drag center. -->
- <attr name="handleDrawable" format="reference" />
-
- <!-- Drawables to use for chevron animations. May be null. -->
- <attr name="chevronDrawables" format="reference"/>
-
- <!-- Drawable to use for wave ripple animation. -->
- <attr name="waveDrawable" format="reference" />
-
- <!-- Outer radius of target circle. Icons will be drawn on this circle. -->
- <attr name="outerRadius" format="dimension" />
-
- <!-- Tactile feedback duration for actions. Set to '0' for no vibration. -->
- <attr name="vibrationDuration" format="integer"/>
-
- <!-- How close we need to be before snapping to a target. -->
- <attr name="snapMargin" format="dimension" />
-
- <!-- Number of waves/chevrons to show in animation. -->
- <attr name="feedbackCount" format="integer" />
-
- <!-- Used when the handle shouldn't wait to be hit before following the finger -->
- <attr name="alwaysTrackFinger" format="boolean" />
- </declare-styleable>
-
- <!-- =============================== -->
<!-- SizeAdaptiveLayout class attributes -->
<!-- =============================== -->
<eat-comment />
@@ -6022,6 +6138,8 @@
<!-- Aspect to use when drawing LockPatternView. Choices are "square"(default), "lock_width"
or "lock_height" -->
<attr name="aspect" format="string" />
+ <!-- Color to use when drawing LockPatternView paths. -->
+ <attr name="pathColor" format="color|reference" />
</declare-styleable>
<!-- Use <code>recognition-service</code> as the root tag of the XML resource that
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 1947c50..d0c455b 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -193,6 +193,9 @@
<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_action_legacy_color_filter">#ff555555</color>
+
<!-- Keyguard colors -->
<color name="keyguard_avatar_frame_color">#ffffffff</color>
<color name="keyguard_avatar_frame_shadow_color">#80000000</color>
diff --git a/core/res/res/values/colors_quantum.xml b/core/res/res/values/colors_quantum.xml
index c8083f4..d10f7c0 100644
--- a/core/res/res/values/colors_quantum.xml
+++ b/core/res/res/values/colors_quantum.xml
@@ -148,13 +148,13 @@
<!-- Text & foreground colors -->
- <color name="primary_text_quantum_light">#ff000000</color>
- <color name="secondary_text_quantum_light">#de000000</color>
- <color name="tertiary_text_quantum_light">#8a000000</color>
+ <color name="primary_text_quantum_light">#de000000</color>
+ <color name="secondary_text_quantum_light">#8a000000</color>
+ <color name="tertiary_text_quantum_light">#4d000000</color>
- <color name="primary_text_quantum_dark">#ffffffff</color>
- <color name="secondary_text_quantum_dark">#deffffff</color>
- <color name="tertiary_text_quantum_dark">#8affffff</color>
+ <color name="primary_text_quantum_dark">#deffffff</color>
+ <color name="secondary_text_quantum_dark">#8affffff</color>
+ <color name="tertiary_text_quantum_dark">#4dffffff</color>
<!-- "Theme" colors to be replaced by attrs when available -->
<color name="theme_color_100">@color/quantum_teal_100</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4656f32..7ae5a03 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -950,7 +950,7 @@
<!-- Max space (in MB) allocated to DownloadManager to store the downloaded
files if they are to be stored in DownloadManager's data dir,
which typically is /data/data/com.android.providers.downloads/files -->
- <integer name="config_downloadDataDirSize">100</integer>
+ <integer name="config_downloadDataDirSize">200</integer>
<!-- Max number of downloads allowed to proceed concurrently -->
<integer name="config_MaxConcurrentDownloadsAllowed">5</integer>
@@ -1339,6 +1339,12 @@
Example: com.google.android.myapp/.resolver.MyResolverActivity -->
<string name="config_customResolverActivity"></string>
+ <!-- Name of the activity that prompts the user to reject, accept, or whitelist
+ an adb host's public key, when an unwhitelisted host connects to the local adbd.
+ Can be customized for other product types -->
+ <string name="config_customAdbPublicKeyActivity"
+ >com.android.systemui/com.android.systemui.usb.UsbDebuggingActivity</string>
+
<!-- Apps that are authorized to access shared accounts, overridden by product overlays -->
<string name="config_appsAuthorizedForSharedAccounts">;com.android.settings;</string>
@@ -1421,4 +1427,5 @@
1 - The device DOES have a permanent menu key; ignore autodetection.
2 - The device DOES NOT have a permanent menu key; ignore autodetection. -->
<integer name="config_overrideHasPermanentMenuKey">0</integer>
+
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 8ec2e6f..94123a2 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -366,4 +366,7 @@
<!-- width of ImmersiveModeConfirmation (-1 for match_parent) -->
<dimen name="immersive_mode_cling_width">-1px</dimen>
+ <!-- radius of the corners of the quantum rounded rect background -->
+ <dimen name="notification_quantum_rounded_rect_radius">2dp</dimen>
+
</resources>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 56bb15f..a79e1fe 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -83,4 +83,5 @@
<item type="id" name="current_scene" />
<item type="id" name="scene_layoutid_cache" />
<item type="id" name="shared_element_name" />
+ <item type="id" name="mask" />
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 64cdc05..8300f38 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2101,6 +2101,8 @@
=============================================================== -->
<eat-comment />
+ <public-padding type="attr" name="l_resource_pad" end="0x1010410" />
+
<public type="attr" name="fragmentBreadCrumbsStyle" />
<public type="attr" name="fastScrollStyle" />
<public type="attr" name="windowContentTransitions" />
@@ -2113,13 +2115,45 @@
<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" />
+ <public type="attr" name="fill" />
+ <public type="attr" name="pathData" />
+ <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="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" />
+ <public type="attr" name="colorControlActivated" />
+ <public type="attr" name="colorButtonNormal" />
+ <public type="attr" name="colorButtonPressed" />
+ <public type="attr" name="colorButtonNormalColored" />
+ <public type="attr" name="colorButtonPressedColored" />
+
+ <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
<public type="dimen" name="recents_thumbnail_height" />
<public type="dimen" name="recents_thumbnail_width" />
+ <public-padding type="id" name="l_resource_pad" end="0x01020040" />
+
<public type="id" name="shared_element_name" />
+ <public type="id" name="mask" />
+
+ <public-padding type="style" name="l_resource_pad" end="0x01030200" />
<public type="style" name="Widget.Holo.FragmentBreadCrumbs" />
<public type="style" name="Widget.Holo.Light.FragmentBreadCrumbs" />
@@ -2215,6 +2249,8 @@
<public type="style" name="Widget.Quantum.Button.Inset" />
<public type="style" name="Widget.Quantum.Button.Small" />
<public type="style" name="Widget.Quantum.Button.Toggle" />
+ <public type="style" name="Widget.Quantum.ButtonBar" />
+ <public type="style" name="Widget.Quantum.ButtonBar.AlertDialog" />
<public type="style" name="Widget.Quantum.CalendarView" />
<public type="style" name="Widget.Quantum.CheckedTextView" />
<public type="style" name="Widget.Quantum.CompoundButton.CheckBox" />
@@ -2246,6 +2282,7 @@
<public type="style" name="Widget.Quantum.RatingBar.Small" />
<public type="style" name="Widget.Quantum.ScrollView" />
<public type="style" name="Widget.Quantum.SeekBar" />
+ <public type="style" name="Widget.Quantum.SegmentedButton" />
<public type="style" name="Widget.Quantum.Spinner" />
<public type="style" name="Widget.Quantum.Tab" />
<public type="style" name="Widget.Quantum.TabWidget" />
@@ -2257,17 +2294,12 @@
<public type="style" name="Widget.Quantum.Light" />
<public type="style" name="Widget.Quantum.Light.ActionBar" />
<public type="style" name="Widget.Quantum.Light.ActionBar.Solid" />
- <public type="style" name="Widget.Quantum.Light.ActionBar.Solid.Inverse" />
<public type="style" name="Widget.Quantum.Light.ActionBar.TabBar" />
- <public type="style" name="Widget.Quantum.Light.ActionBar.TabBar.Inverse" />
<public type="style" name="Widget.Quantum.Light.ActionBar.TabText" />
- <public type="style" name="Widget.Quantum.Light.ActionBar.TabText.Inverse" />
<public type="style" name="Widget.Quantum.Light.ActionBar.TabView" />
- <public type="style" name="Widget.Quantum.Light.ActionBar.TabView.Inverse" />
<public type="style" name="Widget.Quantum.Light.ActionButton" />
<public type="style" name="Widget.Quantum.Light.ActionButton.CloseMode" />
<public type="style" name="Widget.Quantum.Light.ActionButton.Overflow" />
- <public type="style" name="Widget.Quantum.Light.ActionMode.Inverse" />
<public type="style" name="Widget.Quantum.Light.ActionMode" />
<public type="style" name="Widget.Quantum.Light.AutoCompleteTextView" />
<public type="style" name="Widget.Quantum.Light.Button" />
@@ -2275,6 +2307,8 @@
<public type="style" name="Widget.Quantum.Light.Button.Inset" />
<public type="style" name="Widget.Quantum.Light.Button.Small" />
<public type="style" name="Widget.Quantum.Light.Button.Toggle" />
+ <public type="style" name="Widget.Quantum.Light.ButtonBar" />
+ <public type="style" name="Widget.Quantum.Light.ButtonBar.AlertDialog" />
<public type="style" name="Widget.Quantum.Light.CalendarView" />
<public type="style" name="Widget.Quantum.Light.CheckedTextView" />
<public type="style" name="Widget.Quantum.Light.CompoundButton.CheckBox" />
@@ -2308,6 +2342,7 @@
<public type="style" name="Widget.Quantum.Light.RatingBar.Small" />
<public type="style" name="Widget.Quantum.Light.ScrollView" />
<public type="style" name="Widget.Quantum.Light.SeekBar" />
+ <public type="style" name="Widget.Quantum.Light.SegmentedButton" />
<public type="style" name="Widget.Quantum.Light.Spinner" />
<public type="style" name="Widget.Quantum.Light.Tab" />
<public type="style" name="Widget.Quantum.Light.TabWidget" />
@@ -2316,17 +2351,24 @@
<public type="style" name="Widget.Quantum.Light.WebTextView" />
<public type="style" name="Widget.Quantum.Light.WebView" />
- <public type="style" name="Quantum.ButtonBar.AlertDialog" />
- <public type="style" name="Quantum.ButtonBar" />
- <public type="style" name="Quantum.SegmentedButton" />
-
- <public type="style" name="Quantum.Light.ButtonBar.AlertDialog" />
- <public type="style" name="Quantum.Light.ButtonBar" />
- <public type="style" name="Quantum.Light.SegmentedButton" />
-
<public type="style" name="Widget.Quantum.Button.Paper" />
<public type="style" name="Widget.Quantum.Button.Paper.Color" />
<public type="style" name="Widget.Quantum.Light.Button.Paper" />
<public type="style" name="Widget.Quantum.Light.Button.Paper.Color" />
+
+ <public type="style" name="TextAppearance.Quantum.Display4" />
+ <public type="style" name="TextAppearance.Quantum.Display3" />
+ <public type="style" name="TextAppearance.Quantum.Display2" />
+ <public type="style" name="TextAppearance.Quantum.Display1" />
+ <public type="style" name="TextAppearance.Quantum.Headline" />
+ <public type="style" name="TextAppearance.Quantum.Title" />
+ <public type="style" name="TextAppearance.Quantum.Subhead" />
+ <public type="style" name="TextAppearance.Quantum.Body2" />
+ <public type="style" name="TextAppearance.Quantum.Body1" />
+ <public type="style" name="TextAppearance.Quantum.Caption" />
+ <public type="style" name="TextAppearance.Quantum.Menu" />
+ <public type="style" name="TextAppearance.Quantum.Button" />
+
+ <public type="style" name="Widget.Holo.Light.Button.Borderless" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 0699e8b..3a4f059 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3651,6 +3651,16 @@
<!-- Description of an application permission that lets it control keyguard. -->
<string name="permdesc_control_keyguard">Allows an application to control keguard.</string>
+ <!-- Title of an application permission that lets it listen to trust state changes. -->
+ <string name="permlab_trust_listener">Listen to trust state changes.</string>
+ <!-- Description of an application permission that lets it listen to trust state changes. -->
+ <string name="permdesc_trust_listener">Allows an application to listen for changes in trust state.</string>
+
+ <!-- Title of an application permission that lets it bind to a trust agent service. -->
+ <string name="permlab_bind_trust_agent_service">Bind to a trust agent service</string>
+ <!-- Description of an application permission that lets it bind to a trust agent service. -->
+ <string name="permdesc_bind_trust_agent_service">Allows an application to bind to a trust agent service.</string>
+
<!-- Title of an application permission that lets it interact with recovery. -->
<string name="permlab_recovery">Interact with update and recovery system</string>
<!-- Description of an application permission that lets it control keyguard. -->
diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml
index 512c9b8..629b2b7 100644
--- a/core/res/res/values/styles_device_defaults.xml
+++ b/core/res/res/values/styles_device_defaults.xml
@@ -32,731 +32,271 @@
-->
<resources>
<!-- Widget Styles -->
- <style name="Widget.DeviceDefault" parent="Widget.Holo" >
-
- </style>
- <style name="Widget.DeviceDefault.Button" parent="Widget.Holo.Button" >
-
- </style>
- <style name="Widget.DeviceDefault.Button.Small" parent="Widget.Holo.Button.Small" >
-
- </style>
- <style name="Widget.DeviceDefault.Button.Inset" parent="Widget.Holo.Button.Inset" >
-
- </style>
- <style name="Widget.DeviceDefault.Button.Toggle" parent="Widget.Holo.Button.Toggle" >
-
- </style>
- <style name="Widget.DeviceDefault.TextView" parent="Widget.Holo.TextView" >
-
- </style>
- <style name="Widget.DeviceDefault.CheckedTextView" parent="Widget.Holo.CheckedTextView" >
-
- </style>
- <style name="Widget.DeviceDefault.AutoCompleteTextView" parent="Widget.Holo.AutoCompleteTextView" >
-
- </style>
- <style name="Widget.DeviceDefault.CompoundButton.CheckBox" parent="Widget.Holo.CompoundButton.CheckBox" >
-
- </style>
- <style name="Widget.DeviceDefault.ListView.DropDown" parent="Widget.Holo.ListView.DropDown" >
-
- </style>
- <style name="Widget.DeviceDefault.EditText" parent="Widget.Holo.EditText" >
-
- </style>
- <style name="Widget.DeviceDefault.ExpandableListView" parent="Widget.Holo.ExpandableListView" >
-
- </style>
- <style name="Widget.DeviceDefault.GridView" parent="Widget.Holo.GridView" >
-
- </style>
- <style name="Widget.DeviceDefault.ImageButton" parent="Widget.Holo.ImageButton" >
-
- </style>
- <style name="Widget.DeviceDefault.ListView" parent="Widget.Holo.ListView" >
-
- </style>
- <style name="Widget.DeviceDefault.PopupWindow" parent="Widget.Holo.PopupWindow" >
-
- </style>
- <style name="Widget.DeviceDefault.ProgressBar" parent="Widget.Holo.ProgressBar" >
-
- </style>
- <style name="Widget.DeviceDefault.ProgressBar.Horizontal" parent="Widget.Holo.ProgressBar.Horizontal" >
-
- </style>
- <style name="Widget.DeviceDefault.ProgressBar.Small" parent="Widget.Holo.ProgressBar.Small" >
-
- </style>
- <style name="Widget.DeviceDefault.ProgressBar.Small.Title" parent="Widget.Holo.ProgressBar.Small.Title" >
-
- </style>
- <style name="Widget.DeviceDefault.ProgressBar.Large" parent="Widget.Holo.ProgressBar.Large" >
-
- </style>
- <style name="Widget.DeviceDefault.SeekBar" parent="Widget.Holo.SeekBar" >
-
- </style>
- <style name="Widget.DeviceDefault.RatingBar" parent="Widget.Holo.RatingBar" >
-
- </style>
- <style name="Widget.DeviceDefault.RatingBar.Indicator" parent="Widget.Holo.RatingBar.Indicator" >
-
- </style>
- <style name="Widget.DeviceDefault.RatingBar.Small" parent="Widget.Holo.RatingBar.Small" >
-
- </style>
- <style name="Widget.DeviceDefault.CompoundButton.RadioButton" parent="Widget.Holo.CompoundButton.RadioButton" >
-
- </style>
- <style name="Widget.DeviceDefault.ScrollView" parent="Widget.Holo.ScrollView" >
-
- </style>
- <style name="Widget.DeviceDefault.HorizontalScrollView" parent="Widget.Holo.HorizontalScrollView" >
-
- </style>
- <style name="Widget.DeviceDefault.Spinner" parent="Widget.Holo.Spinner" >
-
- </style>
- <style name="Widget.DeviceDefault.CompoundButton.Star" parent="Widget.Holo.CompoundButton.Star" >
-
- </style>
- <style name="Widget.DeviceDefault.TabWidget" parent="Widget.Holo.TabWidget" >
-
- </style>
- <style name="Widget.DeviceDefault.WebTextView" parent="Widget.Holo.WebTextView" >
-
- </style>
- <style name="Widget.DeviceDefault.WebView" parent="Widget.Holo.WebView" >
-
- </style>
- <style name="Widget.DeviceDefault.DropDownItem" parent="Widget.Holo.DropDownItem" >
-
- </style>
- <style name="Widget.DeviceDefault.DropDownItem.Spinner" parent="Widget.Holo.DropDownItem.Spinner" >
-
- </style>
- <style name="Widget.DeviceDefault.TextView.SpinnerItem" parent="Widget.Holo.TextView.SpinnerItem" >
-
- </style>
- <style name="Widget.DeviceDefault.ListPopupWindow" parent="Widget.Holo.ListPopupWindow" >
-
- </style>
- <style name="Widget.DeviceDefault.PopupMenu" parent="Widget.Holo.PopupMenu" >
-
- </style>
- <style name="Widget.DeviceDefault.ActionButton" parent="Widget.Holo.ActionButton" >
-
- </style>
- <style name="Widget.DeviceDefault.ActionButton.Overflow" parent="Widget.Holo.ActionButton.Overflow" >
-
- </style>
- <style name="Widget.DeviceDefault.ActionButton.TextButton" parent="Widget.Holo.ActionButton.TextButton" >
-
- </style>
- <style name="Widget.DeviceDefault.ActionMode" parent="Widget.Holo.ActionMode" >
-
- </style>
- <style name="Widget.DeviceDefault.ActionButton.CloseMode" parent="Widget.Holo.ActionButton.CloseMode" >
-
- </style>
- <style name="Widget.DeviceDefault.ActionBar" parent="Widget.Holo.ActionBar" >
-
- </style>
- <style name="Widget.DeviceDefault.Button.Borderless" parent="Widget.Holo.Button.Borderless" >
-
- </style>
- <style name="Widget.DeviceDefault.Tab" parent="Widget.Holo.Tab" >
-
- </style>
- <style name="Widget.DeviceDefault.CalendarView" parent="Widget.Holo.CalendarView" >
-
- </style>
- <style name="Widget.DeviceDefault.DatePicker" parent="Widget.Holo.DatePicker" >
-
- </style>
- <style name="Widget.DeviceDefault.ActionBar.TabView" parent="Widget.Holo.ActionBar.TabView" >
-
- </style>
- <style name="Widget.DeviceDefault.ActionBar.TabText" parent="Widget.Holo.ActionBar.TabText" >
-
- </style>
- <style name="Widget.DeviceDefault.ActionBar.TabBar" parent="Widget.Holo.ActionBar.TabBar" >
-
- </style>
- <style name="Widget.DeviceDefault.ActionBar.Solid" parent="Widget.Holo.ActionBar.Solid" >
-
- </style>
- <style name="Widget.DeviceDefault.Button.Borderless.Small" parent="Widget.Holo.Button.Borderless.Small" >
-
- </style>
- <style name="Widget.DeviceDefault.AbsListView" parent="Widget.Holo.AbsListView" >
-
- </style>
- <style name="Widget.DeviceDefault.Spinner.DropDown.ActionBar" parent="Widget.Holo.Spinner.DropDown.ActionBar" >
-
- </style>
- <style name="Widget.DeviceDefault.PopupWindow.ActionMode" parent="Widget.Holo.PopupWindow.ActionMode" >
-
- </style>
- <style name="Widget.DeviceDefault.CompoundButton.Switch" parent="Widget.Holo.CompoundButton.Switch">
-
- </style>
- <style name="Widget.DeviceDefault.ExpandableListView.White" parent="Widget.Holo.ExpandableListView.White">
-
- </style>
- <style name="Widget.DeviceDefault.FastScroll" parent="Widget.Holo.FastScroll">
-
- </style>
- <style name="Widget.DeviceDefault.FragmentBreadCrumbs" parent="Widget.Holo.FragmentBreadCrumbs">
-
- </style>
- <style name="Widget.DeviceDefault.Gallery" parent="Widget.Holo.Gallery">
-
- </style>
- <style name="Widget.DeviceDefault.GestureOverlayView" parent="Widget.Holo.GestureOverlayView">
-
- </style>
- <style name="Widget.DeviceDefault.ImageWell" parent="Widget.Holo.ImageWell">
-
- </style>
- <style name="Widget.DeviceDefault.KeyboardView" parent="Widget.Holo.KeyboardView">
-
- </style>
- <style name="Widget.DeviceDefault.ListView.White" parent="Widget.Holo.ListView.White">
-
- </style>
- <style name="Widget.DeviceDefault.NumberPicker" parent="Widget.Holo.NumberPicker">
-
- </style>
- <style name="Widget.DeviceDefault.PreferenceFrameLayout" parent="Widget.Holo.PreferenceFrameLayout">
-
- </style>
- <style name="Widget.DeviceDefault.ProgressBar.Inverse" parent="Widget.Holo.ProgressBar.Inverse">
-
-
- </style>
- <style name="Widget.DeviceDefault.ProgressBar.Large.Inverse" parent="Widget.Holo.ProgressBar.Large.Inverse">
-
- </style>
- <style name="Widget.DeviceDefault.ProgressBar.Small.Inverse" parent="Widget.Holo.ProgressBar.Small.Inverse">
-
- </style>
- <style name="Widget.DeviceDefault.QuickContactBadge.WindowLarge" parent="Widget.Holo.QuickContactBadge.WindowLarge">
-
- </style>
- <style name="Widget.DeviceDefault.QuickContactBadge.WindowMedium" parent="Widget.Holo.QuickContactBadge.WindowMedium">
-
- </style>
- <style name="Widget.DeviceDefault.QuickContactBadge.WindowSmall" parent="Widget.Holo.QuickContactBadge.WindowSmall">
-
- </style>
- <style name="Widget.DeviceDefault.QuickContactBadgeSmall.WindowLarge" parent="Widget.Holo.QuickContactBadgeSmall.WindowLarge">
-
- </style>
- <style name="Widget.DeviceDefault.QuickContactBadgeSmall.WindowMedium" parent="Widget.Holo.QuickContactBadgeSmall.WindowMedium">
-
- </style>
- <style name="Widget.DeviceDefault.QuickContactBadgeSmall.WindowSmall" parent="Widget.Holo.QuickContactBadgeSmall.WindowSmall">
-
- </style>
- <style name="Widget.DeviceDefault.Spinner.DropDown" parent="Widget.Holo.Spinner.DropDown">
-
- </style>
- <style name="Widget.DeviceDefault.StackView" parent="Widget.Holo.StackView">
-
- </style>
- <style name="Widget.DeviceDefault.TextSelectHandle" parent="Widget.Holo.TextSelectHandle">
-
- </style>
- <style name="Widget.DeviceDefault.TextSuggestionsPopupWindow" parent="Widget.Holo.TextSuggestionsPopupWindow">
-
- </style>
- <style name="Widget.DeviceDefault.TextView.ListSeparator" parent="Widget.Holo.TextView.ListSeparator">
-
- </style>
- <style name="Widget.DeviceDefault.TimePicker" parent="Widget.Holo.TimePicker">
-
- </style>
- <style name="Widget.DeviceDefault.Light" parent="Widget.Holo.Light" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.Button" parent="Widget.Holo.Light.Button" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.Button.Small" parent="Widget.Holo.Light.Button.Small" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.Button.Inset" parent="Widget.Holo.Light.Button.Inset" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.Button.Toggle" parent="Widget.Holo.Light.Button.Toggle" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.TextView" parent="Widget.Holo.Light.TextView" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.CheckedTextView" parent="Widget.Holo.Light.CheckedTextView" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.AutoCompleteTextView" parent="Widget.Holo.Light.AutoCompleteTextView" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.CompoundButton.CheckBox" parent="Widget.Holo.Light.CompoundButton.CheckBox" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ListView.DropDown" parent="Widget.Holo.Light.ListView.DropDown" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.EditText" parent="Widget.Holo.Light.EditText" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ExpandableListView" parent="Widget.Holo.Light.ExpandableListView" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.FastScroll" parent="Widget.Holo.Light.FastScroll">
-
- </style>
- <style name="Widget.DeviceDefault.Light.FragmentBreadCrumbs" parent="Widget.Holo.Light.FragmentBreadCrumbs">
-
- </style>
- <style name="Widget.DeviceDefault.Light.GridView" parent="Widget.Holo.Light.GridView" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ImageButton" parent="Widget.Holo.Light.ImageButton" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ListView" parent="Widget.Holo.Light.ListView" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.PopupWindow" parent="Widget.Holo.Light.PopupWindow" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ProgressBar" parent="Widget.Holo.Light.ProgressBar" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ProgressBar.Horizontal" parent="Widget.Holo.Light.ProgressBar.Horizontal" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ProgressBar.Small" parent="Widget.Holo.Light.ProgressBar.Small" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ProgressBar.Small.Title" parent="Widget.Holo.Light.ProgressBar.Small.Title" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ProgressBar.Large" parent="Widget.Holo.Light.ProgressBar.Large" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ProgressBar.Inverse" parent="Widget.Holo.Light.ProgressBar.Inverse" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ProgressBar.Small.Inverse" parent="Widget.Holo.Light.ProgressBar.Small.Inverse" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ProgressBar.Large.Inverse" parent="Widget.Holo.Light.ProgressBar.Large.Inverse" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.SeekBar" parent="Widget.Holo.Light.SeekBar" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.RatingBar" parent="Widget.Holo.Light.RatingBar" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.RatingBar.Indicator" parent="Widget.Holo.Light.RatingBar.Indicator" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.RatingBar.Small" parent="Widget.Holo.Light.RatingBar.Small" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.CompoundButton.RadioButton" parent="Widget.Holo.Light.CompoundButton.RadioButton" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ScrollView" parent="Widget.Holo.Light.ScrollView" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.HorizontalScrollView" parent="Widget.Holo.Light.HorizontalScrollView" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.Spinner" parent="Widget.Holo.Light.Spinner" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.CompoundButton.Star" parent="Widget.Holo.Light.CompoundButton.Star" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.TabWidget" parent="Widget.Holo.Light.TabWidget" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.WebTextView" parent="Widget.Holo.Light.WebTextView" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.WebView" parent="Widget.Holo.Light.WebView" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.DropDownItem" parent="Widget.Holo.Light.DropDownItem" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.DropDownItem.Spinner" parent="Widget.Holo.Light.DropDownItem.Spinner" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.TextView.SpinnerItem" parent="Widget.Holo.Light.TextView.SpinnerItem" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ListPopupWindow" parent="Widget.Holo.Light.ListPopupWindow" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.PopupMenu" parent="Widget.Holo.Light.PopupMenu" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.Tab" parent="Widget.Holo.Light.Tab" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.CalendarView" parent="Widget.Holo.Light.CalendarView" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.Button.Borderless.Small" parent="Widget.Holo.Light.Button.Borderless.Small" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ActionButton" parent="Widget.Holo.Light.ActionButton" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ActionButton.Overflow" parent="Widget.Holo.Light.ActionButton.Overflow" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ActionMode" parent="Widget.Holo.Light.ActionMode" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ActionButton.CloseMode" parent="Widget.Holo.Light.ActionButton.CloseMode" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ActionBar" parent="Widget.Holo.Light.ActionBar" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ActionBar.TabView" parent="Widget.Holo.Light.ActionBar.TabView" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ActionBar.TabText" parent="Widget.Holo.Light.ActionBar.TabText" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ActionBar.TabBar" parent="Widget.Holo.Light.ActionBar.TabBar" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ActionBar.Solid" parent="Widget.Holo.Light.ActionBar.Solid" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ActionBar.Solid.Inverse" parent="Widget.Holo.Light.ActionBar.Solid.Inverse" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ActionBar.TabBar.Inverse" parent="Widget.Holo.Light.ActionBar.TabBar.Inverse" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ActionBar.TabView.Inverse" parent="Widget.Holo.Light.ActionBar.TabView.Inverse" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ActionBar.TabText.Inverse" parent="Widget.Holo.Light.ActionBar.TabText.Inverse" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.ActionMode.Inverse" parent="Widget.Holo.Light.ActionMode.Inverse" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.AbsListView" parent="Widget.Holo.Light.AbsListView" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.Spinner.DropDown.ActionBar" parent="Widget.Holo.Light.Spinner.DropDown.ActionBar" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.PopupWindow.ActionMode" parent="Widget.Holo.Light.PopupWindow.ActionMode" >
-
- </style>
- <style name="Widget.DeviceDefault.Light.Button.Borderless" parent="Widget.Holo.Light.Button.Borderless">
-
- </style>
- <style name="Widget.DeviceDefault.Light.DatePicker" parent="Widget.Holo.Light.DatePicker">
-
- </style>
- <style name="Widget.DeviceDefault.Light.ExpandableListView.White" parent="Widget.Holo.Light.ExpandableListView.White">
-
- </style>
- <style name="Widget.DeviceDefault.Light.Gallery" parent="Widget.Holo.Light.Gallery">
-
- </style>
- <style name="Widget.DeviceDefault.Light.GestureOverlayView" parent="Widget.Holo.Light.GestureOverlayView">
-
- </style>
- <style name="Widget.DeviceDefault.Light.ImageWell" parent="Widget.Holo.Light.ImageWell">
-
- </style>
- <style name="Widget.DeviceDefault.Light.ListView.White" parent="Widget.Holo.Light.ListView.White">
-
- </style>
- <style name="Widget.DeviceDefault.Light.NumberPicker" parent="Widget.Holo.Light.NumberPicker">
-
- </style>
- <style name="Widget.DeviceDefault.Light.Spinner.DropDown" parent="Widget.Holo.Light.Spinner.DropDown">
-
- </style>
- <style name="Widget.DeviceDefault.Light.TextView.ListSeparator" parent="Widget.Holo.Light.TextView.ListSeparator">
-
- </style>
- <style name="Widget.DeviceDefault.Light.TimePicker" parent="Widget.Holo.Light.TimePicker">
-
- </style>
- <style name="Widget.DeviceDefault.Light.TextSuggestionsPopupWindow" parent="Widget.Holo.Light.TextSuggestionsPopupWindow">
-
- </style>
+ <style name="Widget.DeviceDefault" parent="Widget.Quantum"/>
+ <style name="Widget.DeviceDefault.Button" parent="Widget.Quantum.Button"/>
+ <style name="Widget.DeviceDefault.Button.Small" parent="Widget.Quantum.Button.Small"/>
+ <style name="Widget.DeviceDefault.Button.Inset" parent="Widget.Quantum.Button.Inset"/>
+ <style name="Widget.DeviceDefault.Button.Toggle" parent="Widget.Quantum.Button.Toggle"/>
+ <style name="Widget.DeviceDefault.TextView" parent="Widget.Quantum.TextView"/>
+ <style name="Widget.DeviceDefault.CheckedTextView" parent="Widget.Quantum.CheckedTextView"/>
+ <style name="Widget.DeviceDefault.AutoCompleteTextView" parent="Widget.Quantum.AutoCompleteTextView"/>
+ <style name="Widget.DeviceDefault.CompoundButton.CheckBox" parent="Widget.Quantum.CompoundButton.CheckBox"/>
+ <style name="Widget.DeviceDefault.ListView.DropDown" parent="Widget.Quantum.ListView.DropDown"/>
+ <style name="Widget.DeviceDefault.EditText" parent="Widget.Quantum.EditText"/>
+ <style name="Widget.DeviceDefault.ExpandableListView" parent="Widget.Quantum.ExpandableListView"/>
+ <style name="Widget.DeviceDefault.GridView" parent="Widget.Quantum.GridView"/>
+ <style name="Widget.DeviceDefault.ImageButton" parent="Widget.Quantum.ImageButton"/>
+ <style name="Widget.DeviceDefault.ListView" parent="Widget.Quantum.ListView"/>
+ <style name="Widget.DeviceDefault.PopupWindow" parent="Widget.Quantum.PopupWindow"/>
+ <style name="Widget.DeviceDefault.ProgressBar" parent="Widget.Quantum.ProgressBar"/>
+ <style name="Widget.DeviceDefault.ProgressBar.Horizontal" parent="Widget.Quantum.ProgressBar.Horizontal"/>
+ <style name="Widget.DeviceDefault.ProgressBar.Small" parent="Widget.Quantum.ProgressBar.Small"/>
+ <style name="Widget.DeviceDefault.ProgressBar.Small.Title" parent="Widget.Quantum.ProgressBar.Small.Title"/>
+ <style name="Widget.DeviceDefault.ProgressBar.Large" parent="Widget.Quantum.ProgressBar.Large"/>
+ <style name="Widget.DeviceDefault.SeekBar" parent="Widget.Quantum.SeekBar"/>
+ <style name="Widget.DeviceDefault.RatingBar" parent="Widget.Quantum.RatingBar"/>
+ <style name="Widget.DeviceDefault.RatingBar.Indicator" parent="Widget.Quantum.RatingBar.Indicator"/>
+ <style name="Widget.DeviceDefault.RatingBar.Small" parent="Widget.Quantum.RatingBar.Small"/>
+ <style name="Widget.DeviceDefault.CompoundButton.RadioButton" parent="Widget.Quantum.CompoundButton.RadioButton"/>
+ <style name="Widget.DeviceDefault.ScrollView" parent="Widget.Quantum.ScrollView"/>
+ <style name="Widget.DeviceDefault.HorizontalScrollView" parent="Widget.Quantum.HorizontalScrollView"/>
+ <style name="Widget.DeviceDefault.Spinner" parent="Widget.Quantum.Spinner"/>
+ <style name="Widget.DeviceDefault.CompoundButton.Star" parent="Widget.Quantum.CompoundButton.Star"/>
+ <style name="Widget.DeviceDefault.TabWidget" parent="Widget.Quantum.TabWidget"/>
+ <style name="Widget.DeviceDefault.WebTextView" parent="Widget.Quantum.WebTextView"/>
+ <style name="Widget.DeviceDefault.WebView" parent="Widget.Quantum.WebView"/>
+ <style name="Widget.DeviceDefault.DropDownItem" parent="Widget.Quantum.DropDownItem"/>
+ <style name="Widget.DeviceDefault.DropDownItem.Spinner" parent="Widget.Quantum.DropDownItem.Spinner"/>
+ <style name="Widget.DeviceDefault.TextView.SpinnerItem" parent="Widget.Quantum.TextView.SpinnerItem"/>
+ <style name="Widget.DeviceDefault.ListPopupWindow" parent="Widget.Quantum.ListPopupWindow"/>
+ <style name="Widget.DeviceDefault.PopupMenu" parent="Widget.Quantum.PopupMenu"/>
+ <style name="Widget.DeviceDefault.ActionButton" parent="Widget.Quantum.ActionButton"/>
+ <style name="Widget.DeviceDefault.ActionButton.Overflow" parent="Widget.Quantum.ActionButton.Overflow"/>
+ <style name="Widget.DeviceDefault.ActionButton.TextButton" parent="Widget.Quantum.ActionButton.TextButton"/>
+ <style name="Widget.DeviceDefault.ActionMode" parent="Widget.Quantum.ActionMode"/>
+ <style name="Widget.DeviceDefault.ActionButton.CloseMode" parent="Widget.Quantum.ActionButton.CloseMode"/>
+ <style name="Widget.DeviceDefault.ActionBar" parent="Widget.Quantum.ActionBar"/>
+ <style name="Widget.DeviceDefault.Button.Borderless" parent="Widget.Quantum.Button.Borderless"/>
+ <style name="Widget.DeviceDefault.Tab" parent="Widget.Quantum.Tab"/>
+ <style name="Widget.DeviceDefault.CalendarView" parent="Widget.Quantum.CalendarView"/>
+ <style name="Widget.DeviceDefault.DatePicker" parent="Widget.Quantum.DatePicker"/>
+ <style name="Widget.DeviceDefault.ActionBar.TabView" parent="Widget.Quantum.ActionBar.TabView"/>
+ <style name="Widget.DeviceDefault.ActionBar.TabText" parent="Widget.Quantum.ActionBar.TabText"/>
+ <style name="Widget.DeviceDefault.ActionBar.TabBar" parent="Widget.Quantum.ActionBar.TabBar"/>
+ <style name="Widget.DeviceDefault.ActionBar.Solid" parent="Widget.Quantum.ActionBar.Solid"/>
+ <style name="Widget.DeviceDefault.Button.Borderless.Small" parent="Widget.Quantum.Button.Borderless.Small"/>
+ <style name="Widget.DeviceDefault.AbsListView" parent="Widget.Quantum.AbsListView"/>
+ <style name="Widget.DeviceDefault.Spinner.DropDown.ActionBar" parent="Widget.Quantum.Spinner.DropDown.ActionBar"/>
+ <style name="Widget.DeviceDefault.PopupWindow.ActionMode" parent="Widget.Quantum.PopupWindow.ActionMode"/>
+ <style name="Widget.DeviceDefault.CompoundButton.Switch" parent="Widget.Quantum.CompoundButton.Switch"/>
+ <style name="Widget.DeviceDefault.ExpandableListView.White" parent="Widget.Quantum.ExpandableListView.White"/>
+ <style name="Widget.DeviceDefault.FastScroll" parent="Widget.Quantum.FastScroll"/>
+ <style name="Widget.DeviceDefault.FragmentBreadCrumbs" parent="Widget.Quantum.FragmentBreadCrumbs"/>
+ <style name="Widget.DeviceDefault.Gallery" parent="Widget.Quantum.Gallery"/>
+ <style name="Widget.DeviceDefault.GestureOverlayView" parent="Widget.Quantum.GestureOverlayView"/>
+ <style name="Widget.DeviceDefault.ImageWell" parent="Widget.Quantum.ImageWell"/>
+ <style name="Widget.DeviceDefault.KeyboardView" parent="Widget.Quantum.KeyboardView"/>
+ <style name="Widget.DeviceDefault.ListView.White" parent="Widget.Quantum.ListView.White"/>
+ <style name="Widget.DeviceDefault.NumberPicker" parent="Widget.Quantum.NumberPicker"/>
+ <style name="Widget.DeviceDefault.PreferenceFrameLayout" parent="Widget.Quantum.PreferenceFrameLayout"/>
+ <style name="Widget.DeviceDefault.ProgressBar.Inverse" parent="Widget.Quantum.ProgressBar.Inverse"/>
+ <style name="Widget.DeviceDefault.ProgressBar.Large.Inverse" parent="Widget.Quantum.ProgressBar.Large.Inverse"/>
+ <style name="Widget.DeviceDefault.ProgressBar.Small.Inverse" parent="Widget.Quantum.ProgressBar.Small.Inverse"/>
+ <style name="Widget.DeviceDefault.QuickContactBadge.WindowLarge" parent="Widget.Quantum.QuickContactBadge.WindowLarge"/>
+ <style name="Widget.DeviceDefault.QuickContactBadge.WindowMedium" parent="Widget.Quantum.QuickContactBadge.WindowMedium"/>
+ <style name="Widget.DeviceDefault.QuickContactBadge.WindowSmall" parent="Widget.Quantum.QuickContactBadge.WindowSmall"/>
+ <style name="Widget.DeviceDefault.QuickContactBadgeSmall.WindowLarge" parent="Widget.Quantum.QuickContactBadgeSmall.WindowLarge"/>
+ <style name="Widget.DeviceDefault.QuickContactBadgeSmall.WindowMedium" parent="Widget.Quantum.QuickContactBadgeSmall.WindowMedium"/>
+ <style name="Widget.DeviceDefault.QuickContactBadgeSmall.WindowSmall" parent="Widget.Quantum.QuickContactBadgeSmall.WindowSmall"/>
+ <style name="Widget.DeviceDefault.Spinner.DropDown" parent="Widget.Quantum.Spinner.DropDown"/>
+ <style name="Widget.DeviceDefault.StackView" parent="Widget.Quantum.StackView"/>
+ <style name="Widget.DeviceDefault.TextSelectHandle" parent="Widget.Quantum.TextSelectHandle"/>
+ <style name="Widget.DeviceDefault.TextSuggestionsPopupWindow" parent="Widget.Quantum.TextSuggestionsPopupWindow"/>
+ <style name="Widget.DeviceDefault.TextView.ListSeparator" parent="Widget.Quantum.TextView.ListSeparator"/>
+ <style name="Widget.DeviceDefault.TimePicker" parent="Widget.Quantum.TimePicker"/>
+ <style name="Widget.DeviceDefault.Light" parent="Widget.Quantum.Light"/>
+ <style name="Widget.DeviceDefault.Light.Button" parent="Widget.Quantum.Light.Button"/>
+ <style name="Widget.DeviceDefault.Light.Button.Small" parent="Widget.Quantum.Light.Button.Small"/>
+ <style name="Widget.DeviceDefault.Light.Button.Inset" parent="Widget.Quantum.Light.Button.Inset"/>
+ <style name="Widget.DeviceDefault.Light.Button.Toggle" parent="Widget.Quantum.Light.Button.Toggle"/>
+ <style name="Widget.DeviceDefault.Light.TextView" parent="Widget.Quantum.Light.TextView"/>
+ <style name="Widget.DeviceDefault.Light.CheckedTextView" parent="Widget.Quantum.Light.CheckedTextView"/>
+ <style name="Widget.DeviceDefault.Light.AutoCompleteTextView" parent="Widget.Quantum.Light.AutoCompleteTextView"/>
+ <style name="Widget.DeviceDefault.Light.CompoundButton.CheckBox" parent="Widget.Quantum.Light.CompoundButton.CheckBox"/>
+ <style name="Widget.DeviceDefault.Light.ListView.DropDown" parent="Widget.Quantum.Light.ListView.DropDown"/>
+ <style name="Widget.DeviceDefault.Light.EditText" parent="Widget.Quantum.Light.EditText"/>
+ <style name="Widget.DeviceDefault.Light.ExpandableListView" parent="Widget.Quantum.Light.ExpandableListView"/>
+ <style name="Widget.DeviceDefault.Light.FastScroll" parent="Widget.Quantum.Light.FastScroll"/>
+ <style name="Widget.DeviceDefault.Light.FragmentBreadCrumbs" parent="Widget.Quantum.Light.FragmentBreadCrumbs"/>
+ <style name="Widget.DeviceDefault.Light.GridView" parent="Widget.Quantum.Light.GridView"/>
+ <style name="Widget.DeviceDefault.Light.ImageButton" parent="Widget.Quantum.Light.ImageButton"/>
+ <style name="Widget.DeviceDefault.Light.ListView" parent="Widget.Quantum.Light.ListView"/>
+ <style name="Widget.DeviceDefault.Light.PopupWindow" parent="Widget.Quantum.Light.PopupWindow"/>
+ <style name="Widget.DeviceDefault.Light.ProgressBar" parent="Widget.Quantum.Light.ProgressBar"/>
+ <style name="Widget.DeviceDefault.Light.ProgressBar.Horizontal" parent="Widget.Quantum.Light.ProgressBar.Horizontal"/>
+ <style name="Widget.DeviceDefault.Light.ProgressBar.Small" parent="Widget.Quantum.Light.ProgressBar.Small"/>
+ <style name="Widget.DeviceDefault.Light.ProgressBar.Small.Title" parent="Widget.Quantum.Light.ProgressBar.Small.Title"/>
+ <style name="Widget.DeviceDefault.Light.ProgressBar.Large" parent="Widget.Quantum.Light.ProgressBar.Large"/>
+ <style name="Widget.DeviceDefault.Light.ProgressBar.Inverse" parent="Widget.Quantum.Light.ProgressBar.Inverse"/>
+ <style name="Widget.DeviceDefault.Light.ProgressBar.Small.Inverse" parent="Widget.Quantum.Light.ProgressBar.Small.Inverse"/>
+ <style name="Widget.DeviceDefault.Light.ProgressBar.Large.Inverse" parent="Widget.Quantum.Light.ProgressBar.Large.Inverse"/>
+ <style name="Widget.DeviceDefault.Light.SeekBar" parent="Widget.Quantum.Light.SeekBar"/>
+ <style name="Widget.DeviceDefault.Light.RatingBar" parent="Widget.Quantum.Light.RatingBar"/>
+ <style name="Widget.DeviceDefault.Light.RatingBar.Indicator" parent="Widget.Quantum.Light.RatingBar.Indicator"/>
+ <style name="Widget.DeviceDefault.Light.RatingBar.Small" parent="Widget.Quantum.Light.RatingBar.Small"/>
+ <style name="Widget.DeviceDefault.Light.CompoundButton.RadioButton" parent="Widget.Quantum.Light.CompoundButton.RadioButton"/>
+ <style name="Widget.DeviceDefault.Light.ScrollView" parent="Widget.Quantum.Light.ScrollView"/>
+ <style name="Widget.DeviceDefault.Light.HorizontalScrollView" parent="Widget.Quantum.Light.HorizontalScrollView"/>
+ <style name="Widget.DeviceDefault.Light.Spinner" parent="Widget.Quantum.Light.Spinner"/>
+ <style name="Widget.DeviceDefault.Light.CompoundButton.Star" parent="Widget.Quantum.Light.CompoundButton.Star"/>
+ <style name="Widget.DeviceDefault.Light.TabWidget" parent="Widget.Quantum.Light.TabWidget"/>
+ <style name="Widget.DeviceDefault.Light.WebTextView" parent="Widget.Quantum.Light.WebTextView"/>
+ <style name="Widget.DeviceDefault.Light.WebView" parent="Widget.Quantum.Light.WebView"/>
+ <style name="Widget.DeviceDefault.Light.DropDownItem" parent="Widget.Quantum.Light.DropDownItem"/>
+ <style name="Widget.DeviceDefault.Light.DropDownItem.Spinner" parent="Widget.Quantum.Light.DropDownItem.Spinner"/>
+ <style name="Widget.DeviceDefault.Light.TextView.SpinnerItem" parent="Widget.Quantum.Light.TextView.SpinnerItem"/>
+ <style name="Widget.DeviceDefault.Light.ListPopupWindow" parent="Widget.Quantum.Light.ListPopupWindow"/>
+ <style name="Widget.DeviceDefault.Light.PopupMenu" parent="Widget.Quantum.Light.PopupMenu"/>
+ <style name="Widget.DeviceDefault.Light.Tab" parent="Widget.Quantum.Light.Tab"/>
+ <style name="Widget.DeviceDefault.Light.CalendarView" parent="Widget.Quantum.Light.CalendarView"/>
+ <style name="Widget.DeviceDefault.Light.Button.Borderless.Small" parent="Widget.Quantum.Light.Button.Borderless.Small"/>
+ <style name="Widget.DeviceDefault.Light.ActionButton" parent="Widget.Quantum.Light.ActionButton"/>
+ <style name="Widget.DeviceDefault.Light.ActionButton.Overflow" parent="Widget.Quantum.Light.ActionButton.Overflow"/>
+ <style name="Widget.DeviceDefault.Light.ActionMode" parent="Widget.Quantum.Light.ActionMode"/>
+ <style name="Widget.DeviceDefault.Light.ActionButton.CloseMode" parent="Widget.Quantum.Light.ActionButton.CloseMode"/>
+ <style name="Widget.DeviceDefault.Light.ActionBar" parent="Widget.Quantum.Light.ActionBar"/>
+ <style name="Widget.DeviceDefault.Light.ActionBar.TabView" parent="Widget.Quantum.Light.ActionBar.TabView"/>
+ <style name="Widget.DeviceDefault.Light.ActionBar.TabText" parent="Widget.Quantum.Light.ActionBar.TabText"/>
+ <style name="Widget.DeviceDefault.Light.ActionBar.TabBar" parent="Widget.Quantum.Light.ActionBar.TabBar"/>
+ <style name="Widget.DeviceDefault.Light.ActionBar.Solid" parent="Widget.Quantum.Light.ActionBar.Solid"/>
+ <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+ <style name="Widget.DeviceDefault.Light.ActionBar.Solid.Inverse" parent="Widget.Holo.Light.ActionBar.Solid.Inverse"/>
+ <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+ <style name="Widget.DeviceDefault.Light.ActionBar.TabBar.Inverse" parent="Widget.Holo.Light.ActionBar.TabBar.Inverse"/>
+ <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+ <style name="Widget.DeviceDefault.Light.ActionBar.TabView.Inverse" parent="Widget.Holo.Light.ActionBar.TabView.Inverse"/>
+ <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+ <style name="Widget.DeviceDefault.Light.ActionBar.TabText.Inverse" parent="Widget.Holo.Light.ActionBar.TabText.Inverse"/>
+ <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+ <style name="Widget.DeviceDefault.Light.ActionMode.Inverse" parent="Widget.Holo.Light.ActionMode.Inverse"/>
+ <style name="Widget.DeviceDefault.Light.AbsListView" parent="Widget.Quantum.Light.AbsListView"/>
+ <style name="Widget.DeviceDefault.Light.Spinner.DropDown.ActionBar" parent="Widget.Quantum.Light.Spinner.DropDown.ActionBar"/>
+ <style name="Widget.DeviceDefault.Light.PopupWindow.ActionMode" parent="Widget.Quantum.Light.PopupWindow.ActionMode"/>
+ <style name="Widget.DeviceDefault.Light.Button.Borderless" parent="Widget.Quantum.Light.Button.Borderless"/>
+ <style name="Widget.DeviceDefault.Light.DatePicker" parent="Widget.Quantum.Light.DatePicker"/>
+ <style name="Widget.DeviceDefault.Light.ExpandableListView.White" parent="Widget.Quantum.Light.ExpandableListView.White"/>
+ <style name="Widget.DeviceDefault.Light.Gallery" parent="Widget.Quantum.Light.Gallery"/>
+ <style name="Widget.DeviceDefault.Light.GestureOverlayView" parent="Widget.Quantum.Light.GestureOverlayView"/>
+ <style name="Widget.DeviceDefault.Light.ImageWell" parent="Widget.Quantum.Light.ImageWell"/>
+ <style name="Widget.DeviceDefault.Light.ListView.White" parent="Widget.Quantum.Light.ListView.White"/>
+ <style name="Widget.DeviceDefault.Light.NumberPicker" parent="Widget.Quantum.Light.NumberPicker"/>
+ <style name="Widget.DeviceDefault.Light.Spinner.DropDown" parent="Widget.Quantum.Light.Spinner.DropDown"/>
+ <style name="Widget.DeviceDefault.Light.TextView.ListSeparator" parent="Widget.Quantum.Light.TextView.ListSeparator"/>
+ <style name="Widget.DeviceDefault.Light.TimePicker" parent="Widget.Quantum.Light.TimePicker"/>
+ <style name="Widget.DeviceDefault.Light.TextSuggestionsPopupWindow" parent="Widget.Quantum.Light.TextSuggestionsPopupWindow"/>
<!-- Text Appearance Styles -->
- <style name="TextAppearance.DeviceDefault" parent="TextAppearance.Holo" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Inverse" parent="TextAppearance.Holo.Inverse" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Large" parent="TextAppearance.Holo.Large" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Large.Inverse" parent="TextAppearance.Holo.Large.Inverse" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Medium" parent="TextAppearance.Holo.Medium" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Medium.Inverse" parent="TextAppearance.Holo.Medium.Inverse" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Small" parent="TextAppearance.Holo.Small" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Small.Inverse" parent="TextAppearance.Holo.Small.Inverse" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.SearchResult.Title" parent="TextAppearance.Holo.SearchResult.Title" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.SearchResult.Subtitle" parent="TextAppearance.Holo.SearchResult.Subtitle" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget" parent="TextAppearance.Holo.Widget" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.Button" parent="TextAppearance.Holo.Widget.Button" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.IconMenu.Item" parent="TextAppearance.Holo.Widget.IconMenu.Item" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.TabWidget" parent="TextAppearance.Holo.Widget.TabWidget" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.TextView" parent="TextAppearance.Holo.Widget.TextView" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.TextView.PopupMenu" parent="TextAppearance.Holo.Widget.TextView.PopupMenu" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.DropDownHint" parent="TextAppearance.Holo.Widget.DropDownHint" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.DropDownItem" parent="TextAppearance.Holo.Widget.DropDownItem" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.TextView.SpinnerItem" parent="TextAppearance.Holo.Widget.TextView.SpinnerItem" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.EditText" parent="TextAppearance.Holo.Widget.EditText" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.PopupMenu" parent="TextAppearance.Holo.Widget.PopupMenu" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.PopupMenu.Large" parent="TextAppearance.Holo.Widget.PopupMenu.Large" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.PopupMenu.Small" parent="TextAppearance.Holo.Widget.PopupMenu.Small" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Title" parent="TextAppearance.Holo.Widget.ActionBar.Title" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle" parent="TextAppearance.Holo.Widget.ActionBar.Subtitle" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Title" parent="TextAppearance.Holo.Widget.ActionMode.Title" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle" parent="TextAppearance.Holo.Widget.ActionMode.Subtitle" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.WindowTitle" parent="TextAppearance.Holo.WindowTitle" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.DialogWindowTitle" parent="TextAppearance.Holo.DialogWindowTitle" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Title.Inverse" parent="TextAppearance.Holo.Widget.ActionBar.Title.Inverse" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle.Inverse" parent="TextAppearance.Holo.Widget.ActionBar.Subtitle.Inverse" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Title.Inverse" parent="TextAppearance.Holo.Widget.ActionMode.Title.Inverse" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Holo.Widget.ActionMode.Subtitle.Inverse" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Menu" parent="TextAppearance.Holo.Widget.ActionBar.Menu" >
-
- </style>
- <style name="TextAppearance.DeviceDefault.Light" parent="TextAppearance.Holo.Light">
-
- </style>
- <style name="TextAppearance.DeviceDefault.Light.Inverse" parent="TextAppearance.Holo.Light.Inverse">
-
- </style>
- <style name="TextAppearance.DeviceDefault.Light.Large" parent="TextAppearance.Holo.Light.Large">
-
- </style>
- <style name="TextAppearance.DeviceDefault.Light.Large.Inverse" parent="TextAppearance.Holo.Light.Large.Inverse">
-
- </style>
- <style name="TextAppearance.DeviceDefault.Light.Medium" parent="TextAppearance.Holo.Light.Medium">
-
- </style>
- <style name="TextAppearance.DeviceDefault.Light.Medium.Inverse" parent="TextAppearance.Holo.Light.Medium.Inverse">
-
- </style>
- <style name="TextAppearance.DeviceDefault.Light.SearchResult.Subtitle" parent="TextAppearance.Holo.Light.SearchResult.Subtitle">
-
- </style>
- <style name="TextAppearance.DeviceDefault.Light.SearchResult.Title" parent="TextAppearance.Holo.Light.SearchResult.Title">
-
- </style>
- <style name="TextAppearance.DeviceDefault.Light.Small" parent="TextAppearance.Holo.Light.Small">
-
- </style>
- <style name="TextAppearance.DeviceDefault.Light.Small.Inverse" parent="TextAppearance.Holo.Light.Small.Inverse">
-
- </style>
- <style name="TextAppearance.DeviceDefault.Light.Widget.Button" parent="TextAppearance.Holo.Light.Widget.Button">
-
- </style>
- <style name="TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Large" parent="TextAppearance.Holo.Light.Widget.PopupMenu.Large">
-
- </style>
- <style name="TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Small" parent="TextAppearance.Holo.Light.Widget.PopupMenu.Small">
-
- </style>
+ <style name="TextAppearance.DeviceDefault" parent="TextAppearance.Quantum"/>
+ <style name="TextAppearance.DeviceDefault.Inverse" parent="TextAppearance.Quantum.Inverse"/>
+ <style name="TextAppearance.DeviceDefault.Large" parent="TextAppearance.Quantum.Large"/>
+ <style name="TextAppearance.DeviceDefault.Large.Inverse" parent="TextAppearance.Quantum.Large.Inverse"/>
+ <style name="TextAppearance.DeviceDefault.Medium" parent="TextAppearance.Quantum.Medium"/>
+ <style name="TextAppearance.DeviceDefault.Medium.Inverse" parent="TextAppearance.Quantum.Medium.Inverse"/>
+ <style name="TextAppearance.DeviceDefault.Small" parent="TextAppearance.Quantum.Small"/>
+ <style name="TextAppearance.DeviceDefault.Small.Inverse" parent="TextAppearance.Quantum.Small.Inverse"/>
+ <style name="TextAppearance.DeviceDefault.SearchResult.Title" parent="TextAppearance.Quantum.SearchResult.Title"/>
+ <style name="TextAppearance.DeviceDefault.SearchResult.Subtitle" parent="TextAppearance.Quantum.SearchResult.Subtitle"/>
+ <style name="TextAppearance.DeviceDefault.Widget" parent="TextAppearance.Quantum.Widget"/>
+ <style name="TextAppearance.DeviceDefault.Widget.Button" parent="TextAppearance.Quantum.Widget.Button"/>
+ <style name="TextAppearance.DeviceDefault.Widget.IconMenu.Item" parent="TextAppearance.Quantum.Widget.IconMenu.Item"/>
+ <style name="TextAppearance.DeviceDefault.Widget.TabWidget" parent="TextAppearance.Quantum.Widget.TabWidget"/>
+ <style name="TextAppearance.DeviceDefault.Widget.TextView" parent="TextAppearance.Quantum.Widget.TextView"/>
+ <style name="TextAppearance.DeviceDefault.Widget.TextView.PopupMenu" parent="TextAppearance.Quantum.Widget.TextView.PopupMenu"/>
+ <style name="TextAppearance.DeviceDefault.Widget.DropDownHint" parent="TextAppearance.Quantum.Widget.DropDownHint"/>
+ <style name="TextAppearance.DeviceDefault.Widget.DropDownItem" parent="TextAppearance.Quantum.Widget.DropDownItem"/>
+ <style name="TextAppearance.DeviceDefault.Widget.TextView.SpinnerItem" parent="TextAppearance.Quantum.Widget.TextView.SpinnerItem"/>
+ <style name="TextAppearance.DeviceDefault.Widget.EditText" parent="TextAppearance.Quantum.Widget.EditText"/>
+ <style name="TextAppearance.DeviceDefault.Widget.PopupMenu" parent="TextAppearance.Quantum.Widget.PopupMenu"/>
+ <style name="TextAppearance.DeviceDefault.Widget.PopupMenu.Large" parent="TextAppearance.Quantum.Widget.PopupMenu.Large"/>
+ <style name="TextAppearance.DeviceDefault.Widget.PopupMenu.Small" parent="TextAppearance.Quantum.Widget.PopupMenu.Small"/>
+ <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Title" parent="TextAppearance.Quantum.Widget.ActionBar.Title"/>
+ <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle" parent="TextAppearance.Quantum.Widget.ActionBar.Subtitle"/>
+ <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Title" parent="TextAppearance.Quantum.Widget.ActionMode.Title"/>
+ <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle" parent="TextAppearance.Quantum.Widget.ActionMode.Subtitle"/>
+ <style name="TextAppearance.DeviceDefault.WindowTitle" parent="TextAppearance.Quantum.WindowTitle"/>
+ <style name="TextAppearance.DeviceDefault.DialogWindowTitle" parent="TextAppearance.Quantum.DialogWindowTitle"/>
+ <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+ <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Title.Inverse" parent="TextAppearance.Quantum.Widget.ActionBar.Title.Inverse"/>
+ <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+ <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle.Inverse" parent="TextAppearance.Quantum.Widget.ActionBar.Subtitle.Inverse"/>
+ <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+ <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Title.Inverse" parent="TextAppearance.Quantum.Widget.ActionMode.Title.Inverse"/>
+ <!-- @deprecated Action bars are now themed using the inheritable android:theme attribute. -->
+ <style name="TextAppearance.DeviceDefault.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Quantum.Widget.ActionMode.Subtitle.Inverse"/>
+ <style name="TextAppearance.DeviceDefault.Widget.ActionBar.Menu" parent="TextAppearance.Quantum.Widget.ActionBar.Menu"/>
+ <style name="TextAppearance.DeviceDefault.Light" parent="TextAppearance.Quantum.Light"/>
+ <style name="TextAppearance.DeviceDefault.Light.Inverse" parent="TextAppearance.Quantum.Light.Inverse"/>
+ <style name="TextAppearance.DeviceDefault.Light.Large" parent="TextAppearance.Quantum.Light.Large"/>
+ <style name="TextAppearance.DeviceDefault.Light.Large.Inverse" parent="TextAppearance.Quantum.Light.Large.Inverse"/>
+ <style name="TextAppearance.DeviceDefault.Light.Medium" parent="TextAppearance.Quantum.Light.Medium"/>
+ <style name="TextAppearance.DeviceDefault.Light.Medium.Inverse" parent="TextAppearance.Quantum.Light.Medium.Inverse"/>
+ <style name="TextAppearance.DeviceDefault.Light.SearchResult.Subtitle" parent="TextAppearance.Quantum.Light.SearchResult.Subtitle"/>
+ <style name="TextAppearance.DeviceDefault.Light.SearchResult.Title" parent="TextAppearance.Quantum.Light.SearchResult.Title"/>
+ <style name="TextAppearance.DeviceDefault.Light.Small" parent="TextAppearance.Quantum.Light.Small"/>
+ <style name="TextAppearance.DeviceDefault.Light.Small.Inverse" parent="TextAppearance.Quantum.Light.Small.Inverse"/>
+ <style name="TextAppearance.DeviceDefault.Light.Widget.Button" parent="TextAppearance.Quantum.Light.Widget.Button"/>
+ <style name="TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Large" parent="TextAppearance.Quantum.Light.Widget.PopupMenu.Large"/>
+ <style name="TextAppearance.DeviceDefault.Light.Widget.PopupMenu.Small" parent="TextAppearance.Quantum.Light.Widget.PopupMenu.Small"/>
<!-- Preference Styles -->
- <style name="Preference.DeviceDefault" parent="Preference.Holo">
-
- </style>
- <style name="Preference.DeviceDefault.Category" parent="Preference.Holo.Category">
-
- </style>
- <style name="Preference.DeviceDefault.CheckBoxPreference" parent="Preference.Holo.CheckBoxPreference">
-
- </style>
- <style name="Preference.DeviceDefault.DialogPreference" parent="Preference.Holo.DialogPreference">
-
- </style>
- <style name="Preference.DeviceDefault.DialogPreference.EditTextPreference" parent="Preference.Holo.DialogPreference.EditTextPreference">
-
- </style>
- <style name="Preference.DeviceDefault.DialogPreference.YesNoPreference" parent="Preference.Holo.DialogPreference.YesNoPreference">
-
- </style>
- <style name="Preference.DeviceDefault.Information" parent="Preference.Holo.Information">
-
- </style>
- <style name="Preference.DeviceDefault.PreferenceScreen" parent="Preference.Holo.PreferenceScreen">
-
- </style>
- <style name="Preference.DeviceDefault.RingtonePreference" parent="Preference.Holo.RingtonePreference">
-
- </style>
- <style name="Preference.DeviceDefault.SwitchPreference" parent="Preference.Holo.SwitchPreference">
-
- </style>
+ <style name="Preference.DeviceDefault" parent="Preference.Quantum"/>
+ <style name="Preference.DeviceDefault.Category" parent="Preference.Quantum.Category"/>
+ <style name="Preference.DeviceDefault.CheckBoxPreference" parent="Preference.Quantum.CheckBoxPreference"/>
+ <style name="Preference.DeviceDefault.DialogPreference" parent="Preference.Quantum.DialogPreference"/>
+ <style name="Preference.DeviceDefault.DialogPreference.EditTextPreference" parent="Preference.Quantum.DialogPreference.EditTextPreference"/>
+ <style name="Preference.DeviceDefault.DialogPreference.YesNoPreference" parent="Preference.Quantum.DialogPreference.YesNoPreference"/>
+ <style name="Preference.DeviceDefault.Information" parent="Preference.Quantum.Information"/>
+ <style name="Preference.DeviceDefault.PreferenceScreen" parent="Preference.Quantum.PreferenceScreen"/>
+ <style name="Preference.DeviceDefault.RingtonePreference" parent="Preference.Quantum.RingtonePreference"/>
+ <style name="Preference.DeviceDefault.SwitchPreference" parent="Preference.Quantum.SwitchPreference"/>
<!-- AlertDialog Styles -->
- <style name="AlertDialog.DeviceDefault" parent="AlertDialog.Holo">
-
- </style>
- <style name="AlertDialog.DeviceDefault.Light" parent="AlertDialog.Holo.Light" >
-
- </style>
+ <style name="AlertDialog.DeviceDefault" parent="AlertDialog.Quantum"/>
+ <style name="AlertDialog.DeviceDefault.Light" parent="AlertDialog.Quantum.Light"/>
<!-- Animation Styles -->
- <style name="Animation.DeviceDefault.Activity" parent="Animation.Holo.Activity">
-
- </style>
- <style name="Animation.DeviceDefault.Dialog" parent="Animation.Holo.Dialog">
-
- </style>
+ <style name="Animation.DeviceDefault.Activity" parent="Animation.Quantum.Activity"/>
+ <style name="Animation.DeviceDefault.Dialog" parent="Animation.Quantum.Dialog"/>
<!-- DialogWindowTitle Styles -->
- <style name="DialogWindowTitle.DeviceDefault" parent="DialogWindowTitle.Holo">
-
- </style>
- <style name="DialogWindowTitle.DeviceDefault.Light" parent="DialogWindowTitle.Holo.Light">
-
- </style>
+ <style name="DialogWindowTitle.DeviceDefault" parent="DialogWindowTitle.Quantum"/>
+ <style name="DialogWindowTitle.DeviceDefault.Light" parent="DialogWindowTitle.Quantum.Light"/>
<!-- WindowTitle Styles -->
- <style name="WindowTitle.DeviceDefault" parent="WindowTitle.Holo">
-
- </style>
- <style name="WindowTitleBackground.DeviceDefault" parent="WindowTitleBackground.Holo">
-
- </style>
+ <style name="WindowTitle.DeviceDefault" parent="WindowTitle.Quantum"/>
+ <style name="WindowTitleBackground.DeviceDefault" parent="WindowTitleBackground.Quantum"/>
<!-- Other Styles -->
- <style name="DeviceDefault.ButtonBar" parent="Holo.ButtonBar" >
+ <style name="DeviceDefault.ButtonBar" parent="Widget.Quantum.ButtonBar"/>
+ <style name="DeviceDefault.ButtonBar.AlertDialog" parent="Widget.Quantum.ButtonBar.AlertDialog"/>
+ <style name="DeviceDefault.SegmentedButton" parent="Widget.Quantum.SegmentedButton"/>
+ <style name="DeviceDefault.Light.ButtonBar" parent="Widget.Quantum.Light.ButtonBar"/>
+ <style name="DeviceDefault.Light.ButtonBar.AlertDialog" parent="Widget.Quantum.Light.ButtonBar.AlertDialog"/>
+ <style name="DeviceDefault.Light.SegmentedButton" parent="Widget.Quantum.Light.SegmentedButton"/>
- </style>
- <style name="DeviceDefault.ButtonBar.AlertDialog" parent="Holo.ButtonBar.AlertDialog" >
+ <style name="Widget.DeviceDefault.MediaRouteButton" parent="Widget.Quantum.MediaRouteButton" />
+ <style name="Widget.DeviceDefault.Light.MediaRouteButton" parent="Widget.Quantum.Light.MediaRouteButton" />
- </style>
- <style name="DeviceDefault.SegmentedButton" parent="Holo.SegmentedButton" >
-
- </style>
- <style name="DeviceDefault.Light.ButtonBar" parent="Holo.Light.ButtonBar" >
-
- </style>
- <style name="DeviceDefault.Light.ButtonBar.AlertDialog" parent="Holo.Light.ButtonBar.AlertDialog" >
-
- </style>
- <style name="DeviceDefault.Light.SegmentedButton" parent="Holo.Light.SegmentedButton" >
-
- </style>
-
- <style name="Widget.DeviceDefault.MediaRouteButton" parent="Widget.Holo.MediaRouteButton" />
- <style name="Widget.DeviceDefault.Light.MediaRouteButton" parent="Widget.Holo.Light.MediaRouteButton" />
-
- <style name="TextAppearance.DeviceDefault.TimePicker.TimeLabel" parent="TextAppearance.Holo.TimePicker.TimeLabel">
- </style>
-
- <style name="TextAppearance.DeviceDefault.Light.TimePicker.TimeLabel" parent="TextAppearance.Holo.Light.TimePicker.TimeLabel">
- </style>
-
- <style name="TextAppearance.DeviceDefault.TimePicker.AmPmLabel" parent="TextAppearance.Holo.TimePicker.AmPmLabel">
- </style>
-
- <style name="TextAppearance.DeviceDefault.Light.TimePicker.AmPmLabel" parent="TextAppearance.Holo.Light.TimePicker.AmPmLabel">
- </style>
-
- <style name="Theme.DeviceDefault.Dialog.TimePicker" parent="Theme.Holo.Dialog.TimePicker">
- </style>
-
- <style name="Theme.DeviceDefault.Light.Dialog.TimePicker" parent="Theme.Holo.Light.Dialog.TimePicker">
- </style>
-
+ <style name="TextAppearance.DeviceDefault.TimePicker.TimeLabel" parent="TextAppearance.Quantum.TimePicker.TimeLabel"/>
+ <style name="TextAppearance.DeviceDefault.Light.TimePicker.TimeLabel" parent="TextAppearance.Quantum.Light.TimePicker.TimeLabel"/>
+ <style name="TextAppearance.DeviceDefault.TimePicker.AmPmLabel" parent="TextAppearance.Quantum.TimePicker.AmPmLabel"/>
+ <style name="TextAppearance.DeviceDefault.Light.TimePicker.AmPmLabel" parent="TextAppearance.Quantum.Light.TimePicker.AmPmLabel"/>
+ <style name="Theme.DeviceDefault.Dialog.TimePicker" parent="Theme.Quantum.Dialog.TimePicker"/>
+ <style name="Theme.DeviceDefault.Light.Dialog.TimePicker" parent="Theme.Quantum.Light.Dialog.TimePicker"/>
</resources>
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index 44cdb5f..85d8761 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -30,7 +30,7 @@
-->
<resources>
<!-- Preference styles -->
- <eat-comment />
+ <eat-comment/>
<style name="Preference.Quantum">
<item name="layout">@layout/preference_holo</item>
@@ -90,16 +90,98 @@
<!-- Text styles -->
- <style name="TextAppearance.Quantum" parent="TextAppearance"/>
+ <style name="TextAppearance.Quantum">
+ <item name="textColor">?textColorPrimary</item>
+ <item name="textColorHint">?textColorHint</item>
+ <item name="textColorHighlight">?textColorHighlight</item>
+ <item name="textColorLink">?textColorLink</item>
+ <item name="textSize">@dimen/text_size_body_1_quantum</item>
+ <item name="fontFamily">@string/font_family_body_1_quantum</item>
+ </style>
- <style name="TextAppearance.Quantum.Inverse" parent="TextAppearance.Inverse">
+ <style name="TextAppearance.Quantum.Display4">
+ <item name="textSize">@dimen/text_size_display_4_quantum</item>
+ <item name="fontFamily">@string/font_family_display_4_quantum</item>
+ <item name="textColor">?textColorSecondary</item>
+ </style>
+
+ <style name="TextAppearance.Quantum.Display3">
+ <item name="textSize">@dimen/text_size_display_3_quantum</item>
+ <item name="fontFamily">@string/font_family_display_3_quantum</item>
+ <item name="textColor">?textColorSecondary</item>
+ </style>
+
+ <style name="TextAppearance.Quantum.Display2">
+ <item name="textSize">@dimen/text_size_display_2_quantum</item>
+ <item name="fontFamily">@string/font_family_display_2_quantum</item>
+ <item name="textColor">?textColorSecondary</item>
+ </style>
+
+ <style name="TextAppearance.Quantum.Display1">
+ <item name="textSize">@dimen/text_size_display_1_quantum</item>
+ <item name="fontFamily">@string/font_family_display_1_quantum</item>
+ <item name="textColor">?textColorSecondary</item>
+ </style>
+
+ <style name="TextAppearance.Quantum.Headline">
+ <item name="textSize">@dimen/text_size_headline_quantum</item>
+ <item name="fontFamily">@string/font_family_headline_quantum</item>
+ <item name="textColor">?textColorPrimary</item>
+ </style>
+
+ <style name="TextAppearance.Quantum.Title">
+ <item name="textSize">@dimen/text_size_title_quantum</item>
+ <item name="fontFamily">@string/font_family_title_quantum</item>
+ <item name="textColor">?textColorPrimary</item>
+ </style>
+
+ <style name="TextAppearance.Quantum.Subhead">
+ <item name="textSize">@dimen/text_size_subhead_quantum</item>
+ <item name="fontFamily">@string/font_family_subhead_quantum</item>
+ <item name="textColor">?textColorPrimary</item>
+ </style>
+
+ <style name="TextAppearance.Quantum.Body2">
+ <item name="textSize">@dimen/text_size_body_2_quantum</item>
+ <item name="fontFamily">@string/font_family_body_2_quantum</item>
+ <item name="textColor">?textColorPrimary</item>
+ </style>
+
+ <style name="TextAppearance.Quantum.Body1">
+ <item name="textSize">@dimen/text_size_body_1_quantum</item>
+ <item name="fontFamily">@string/font_family_body_1_quantum</item>
+ <item name="textColor">?textColorPrimary</item>
+ </style>
+
+ <style name="TextAppearance.Quantum.Caption">
+ <item name="textSize">@dimen/text_size_caption_quantum</item>
+ <item name="fontFamily">@string/font_family_caption_quantum</item>
+ <item name="textColor">?textColorSecondary</item>
+ </style>
+
+ <style name="TextAppearance.Quantum.Menu">
+ <item name="textSize">@dimen/text_size_menu_quantum</item>
+ <item name="fontFamily">@string/font_family_menu_quantum</item>
+ <item name="textColor">?textColorPrimary</item>
+ </style>
+
+ <style name="TextAppearance.Quantum.Button">
+ <item name="textSize">@dimen/text_size_button_quantum</item>
+ <item name="fontFamily">@string/font_family_button_quantum</item>
+ <item name="textAllCaps">true</item>
+ <item name="textColor">?textColorPrimary</item>
+ </style>
+
+ <!-- Deprecated text styles -->
+
+ <style name="TextAppearance.Quantum.Inverse">
<item name="textColor">?attr/textColorPrimaryInverse</item>
<item name="textColorHint">?attr/textColorHintInverse</item>
<item name="textColorHighlight">?attr/textColorHighlightInverse</item>
<item name="textColorLink">?attr/textColorLinkInverse</item>
</style>
- <style name="TextAppearance.Quantum.Large" parent="TextAppearance.Large"/>
+ <style name="TextAppearance.Quantum.Large" parent="TextAppearance.Quantum.Headline" />
<style name="TextAppearance.Quantum.Large.Inverse">
<item name="textColor">?attr/textColorPrimaryInverse</item>
@@ -108,7 +190,7 @@
<item name="textColorLink">?attr/textColorLinkInverse</item>
</style>
- <style name="TextAppearance.Quantum.Medium" parent="TextAppearance.Medium"/>
+ <style name="TextAppearance.Quantum.Medium" parent="TextAppearance.Quantum.Body1" />
<style name="TextAppearance.Quantum.Medium.Inverse">
<item name="textColor">?attr/textColorSecondaryInverse</item>
@@ -117,65 +199,50 @@
<item name="textColorLink">?attr/textColorLinkInverse</item>
</style>
- <style name="TextAppearance.Quantum.Small" parent="TextAppearance.Small"/>
+ <style name="TextAppearance.Quantum.Small" parent="TextAppearance.Quantum.Caption" />
<style name="TextAppearance.Quantum.Small.Inverse">
- <item name="textColor">?attr/textColorSecondaryInverse</item>
+ <item name="textColor">?attr/textColorTertiaryInverse</item>
<item name="textColorHint">?attr/textColorHintInverse</item>
<item name="textColorHighlight">?attr/textColorHighlightInverse</item>
<item name="textColorLink">?attr/textColorLinkInverse</item>
</style>
<style name="TextAppearance.Quantum.SearchResult">
- <item name="textStyle">normal</item>
- <item name="textColor">?attr/textColorPrimary</item>
- <item name="textColorHint">?attr/textColorHint</item>
</style>
- <style name="TextAppearance.Quantum.SearchResult.Title">
- <item name="textSize">18sp</item>
- </style>
+ <style name="TextAppearance.Quantum.SearchResult.Title" parent="TextAppearance.Quantum.Title" />
+ <style name="TextAppearance.Quantum.SearchResult.Subtitle" parent="TextAppearance.Quantum.Subhead" />
- <style name="TextAppearance.Quantum.SearchResult.Subtitle">
- <item name="textSize">14sp</item>
- <item name="textColor">?attr/textColorSecondary</item>
- </style>
-
- <style name="TextAppearance.Quantum.Widget" parent="TextAppearance.Widget"/>
-
- <style name="TextAppearance.Quantum.Widget.Button">
- <item name="fontFamily">@string/font_family_button_quantum</item>
- <item name="textSize">@dimen/text_size_button_quantum</item>
- <item name="textAllCaps">true</item>
- <item name="textColor">?attr/textColorPrimary</item>
- <item name="textStyle">normal</item>
- </style>
+ <style name="TextAppearance.Quantum.Widget"/>
+ <style name="TextAppearance.Quantum.Widget.Button" parent="TextAppearance.Quantum.Button" />
<style name="TextAppearance.Quantum.Widget.EditText">
- <item name="textColor">?textColorPrimaryInverse</item>
- <item name="textColorHint">?textColorHintInverse</item>
+ <item name="textColor">?attr/textColorPrimaryInverse</item>
+ <item name="textColorHint">?attr/textColorHintInverse</item>
</style>
- <style name="TextAppearance.Quantum.Widget.Switch" parent="TextAppearance.Quantum.Small">
- <item name="textColor">@color/secondary_text_quantum_dark</item>
+ <style name="TextAppearance.Quantum.Widget.Switch">
+ <item name="textSize">14sp</item>
</style>
- <style name="TextAppearance.Quantum.Widget.PopupMenu" parent="TextAppearance.Widget.PopupMenu">
- <item name="textColor">?attr/textColorPrimary</item>
- </style>
+ <style name="TextAppearance.Quantum.Widget.PopupMenu"/>
<style name="TextAppearance.Quantum.Widget.PopupMenu.Large">
- <item name="textSize">18sp</item>
+ <item name="fontFamily">@string/font_family_menu_quantum</item>
+ <item name="textSize">@dimen/text_size_menu_quantum</item>>
</style>
<style name="TextAppearance.Quantum.Widget.PopupMenu.Small">
- <item name="textSize">14sp</item>
+ <item name="fontFamily">@string/font_family_menu_quantum</item>
+ <item name="textSize">@dimen/text_size_menu_quantum</item>>
</style>
<style name="TextAppearance.Quantum.Widget.DropDownHint">
- <item name="textColor">?attr/textColorPrimary</item>
- <item name="textSize">14sp</item>
+ <item name="fontFamily">@string/font_family_menu_quantum</item>
+ <item name="textSize">@dimen/text_size_menu_quantum</item>>
</style>
+
<style name="TextAppearance.Quantum.Widget.IconMenu.Item" parent="TextAppearance.Quantum.Small">
<item name="textColor">?attr/textColorPrimary</item>
</style>
@@ -194,10 +261,11 @@
</style>
<style name="TextAppearance.Quantum.Widget.TextView.PopupMenu">
- <item name="textSize">18sp</item>
+ <item name="fontFamily">@string/font_family_menu_quantum</item>
+ <item name="textSize">@dimen/text_size_menu_quantum</item>
</style>
- <style name="TextAppearance.Quantum.Widget.TextView.SpinnerItem" />
+ <style name="TextAppearance.Quantum.Widget.TextView.SpinnerItem"/>
<style name="TextAppearance.Quantum.Widget.DropDownItem">
<item name="textColor">?attr/textColorPrimaryDisableOnly</item>
@@ -209,121 +277,124 @@
<item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
</style>
+ <style name="TextAppearance.Quantum.Widget.ActionMode.Title.Inverse" parent="TextAppearance.Quantum.Medium.Inverse">
+ <item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
+ </style>
+
<style name="TextAppearance.Quantum.Widget.ActionMode.Subtitle" parent="TextAppearance.Quantum.Small">
<item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
</style>
+ <style name="TextAppearance.Quantum.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Quantum.Small.Inverse">
+ <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
+ </style>
+
<!-- Text styles with no light versions -->
<style name="TextAppearance.Quantum.Widget.ActionBar.Title" parent="TextAppearance.Quantum.Medium">
<item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
</style>
- <style name="TextAppearance.Quantum.Widget.ActionBar.Subtitle" parent="TextAppearance.Quantum.Small">
- <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
- </style>
-
<style name="TextAppearance.Quantum.Widget.ActionBar.Title.Inverse" parent="TextAppearance.Quantum.Medium.Inverse">
<item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
</style>
+ <style name="TextAppearance.Quantum.Widget.ActionBar.Subtitle" parent="TextAppearance.Quantum.Small">
+ <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
+ </style>
+
<style name="TextAppearance.Quantum.Widget.ActionBar.Subtitle.Inverse" parent="TextAppearance.Quantum.Small.Inverse">
<item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
</style>
<style name="TextAppearance.Quantum.Widget.ActionBar.Menu" parent="TextAppearance.Quantum.Small">
- <item name="textSize">12sp</item>
- <item name="textStyle">bold</item>
+ <item name="fontFamily">@string/font_family_menu_quantum</item>
+ <item name="textSize">@dimen/text_size_menu_quantum</item>>
<item name="textColor">?attr/actionMenuTextColor</item>
<item name="textAllCaps">@bool/config_actionMenuItemAllCaps</item>
</style>
- <style name="TextAppearance.Quantum.Widget.ActionMode.Title.Inverse" parent="TextAppearance.Quantum.Medium.Inverse">
- <item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
- </style>
-
- <style name="TextAppearance.Quantum.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Quantum.Small.Inverse">
- <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
+ <style name="TextAppearance.Quantum.Widget.ActionBar.Menu.Inverse" parent="TextAppearance.Quantum.Small.Inverse">
+ <item name="fontFamily">@string/font_family_menu_quantum</item>
+ <item name="textSize">@dimen/text_size_menu_quantum</item>>
+ <item name="textColor">?attr/actionMenuTextColor</item>
+ <item name="textAllCaps">@bool/config_actionMenuItemAllCaps</item>
</style>
<style name="TextAppearance.Quantum.WindowTitle">
<item name="textColor">?attr/textColorPrimary</item>
- <item name="textSize">14sp</item>
- <item name="textStyle">bold</item>
+ <item name="fontFamily">@string/font_family_headline_quantum</item>
+ <item name="textSize">@dimen/text_size_headline_quantum</item>
</style>
<style name="TextAppearance.Quantum.DialogWindowTitle">
- <item name="textSize">22sp</item>
+ <item name="fontFamily">@string/font_family_headline_quantum</item>
+ <item name="textSize">@dimen/text_size_headline_quantum</item>
<item name="textColor">?attr/textColorPrimary</item>
</style>
- <style name="TextAppearance.Quantum.CalendarViewWeekDayView" parent="TextAppearance.Small.CalendarViewWeekDayView">
+ <style name="TextAppearance.Quantum.CalendarViewWeekDayView" parent="TextAppearance.Quantum.Small">
+ <item name="textStyle">bold</item>
<item name="textColor">#505050</item>
</style>
+ <style name="TextAppearance.Quantum.TimePicker.TimeLabel" parent="TextAppearance.Quantum">
+ <item name="textSize">@dimen/timepicker_time_label_size</item>
+ <item name="textColor">@color/timepicker_default_text_color_quantum_dark</item>
+ </style>
+
+ <style name="TextAppearance.Quantum.TimePicker.AmPmLabel" parent="TextAppearance.Quantum">
+ <item name="textSize">@dimen/timepicker_ampm_label_size</item>
+ <item name="textAllCaps">true</item>
+ <item name="textColor">@color/timepicker_default_text_color_quantum_dark</item>
+ <item name="textStyle">bold</item>
+ </style>
+
<!-- Light text styles -->
<style name="TextAppearance.Quantum.Light" parent="TextAppearance.Quantum"/>
-
- <style name="TextAppearance.Quantum.Light.Inverse" parent="TextAppearance.Quantum.Inverse" />
-
+ <style name="TextAppearance.Quantum.Light.Inverse" parent="TextAppearance.Quantum.Inverse"/>
<style name="TextAppearance.Quantum.Light.Large" parent="TextAppearance.Quantum.Large"/>
-
+ <style name="TextAppearance.Quantum.Light.Large.Inverse" parent="TextAppearance.Quantum.Large.Inverse"/>
<style name="TextAppearance.Quantum.Light.Medium" parent="TextAppearance.Quantum.Medium"/>
-
+ <style name="TextAppearance.Quantum.Light.Medium.Inverse" parent="TextAppearance.Quantum.Medium.Inverse"/>
<style name="TextAppearance.Quantum.Light.Small" parent="TextAppearance.Quantum.Small"/>
+ <style name="TextAppearance.Quantum.Light.Small.Inverse" parent="TextAppearance.Quantum.Small.Inverse"/>
+ <style name="TextAppearance.Quantum.Light.SearchResult" parent="TextAppearance.Quantum.SearchResult"/>
+ <style name="TextAppearance.Quantum.Light.SearchResult.Title" parent="TextAppearance.Quantum.SearchResult.Title"/>
+ <style name="TextAppearance.Quantum.Light.SearchResult.Subtitle" parent="TextAppearance.Quantum.SearchResult.Subtitle"/>
+ <style name="TextAppearance.Quantum.Light.Widget" parent="TextAppearance.Quantum.Widget"/>
+ <style name="TextAppearance.Quantum.Light.Widget.Button" parent="TextAppearance.Quantum.Widget.Button"/>
+ <style name="TextAppearance.Quantum.Light.Widget.EditText" parent="TextAppearance.Quantum.Widget.EditText"/>
+ <style name="TextAppearance.Quantum.Light.Widget.Switch" parent="TextAppearance.Quantum.Widget.Switch"/>
+ <style name="TextAppearance.Quantum.Light.Widget.PopupMenu" parent="TextAppearance.Quantum.Widget.PopupMenu"/>
+ <style name="TextAppearance.Quantum.Light.Widget.PopupMenu.Large" parent="TextAppearance.Quantum.Widget.PopupMenu.Large"/>
+ <style name="TextAppearance.Quantum.Light.Widget.PopupMenu.Small" parent="TextAppearance.Quantum.Widget.PopupMenu.Small"/>
+ <style name="TextAppearance.Quantum.Light.Widget.DropDownHint" parent="TextAppearance.Quantum.Widget.DropDownHint"/>
+ <style name="TextAppearance.Quantum.Light.Widget.ActionMode.Title" parent="TextAppearance.Quantum.Widget.ActionMode.Title"/>
+ <style name="TextAppearance.Quantum.Light.Widget.ActionMode.Subtitle" parent="TextAppearance.Quantum.Widget.ActionMode.Subtitle"/>
+ <style name="TextAppearance.Quantum.Light.WindowTitle" parent="TextAppearance.Quantum.WindowTitle"/>
+ <style name="TextAppearance.Quantum.Light.DialogWindowTitle" parent="TextAppearance.Quantum.DialogWindowTitle"/>
+ <style name="TextAppearance.Quantum.Light.CalendarViewWeekDayView" parent="TextAppearance.Quantum.CalendarViewWeekDayView"/>
- <style name="TextAppearance.Quantum.Light.Large.Inverse" parent="TextAppearance.Quantum.Large.Inverse" />
-
- <style name="TextAppearance.Quantum.Light.Medium.Inverse" parent="TextAppearance.Quantum.Medium.Inverse" />
-
- <style name="TextAppearance.Quantum.Light.Small.Inverse" parent="TextAppearance.Quantum.Small.Inverse" />
-
- <style name="TextAppearance.Quantum.Light.SearchResult" parent="TextAppearance.Quantum.SearchResult" />
-
- <style name="TextAppearance.Quantum.Light.SearchResult.Title" parent="TextAppearance.Quantum.SearchResult.Title" />
-
- <style name="TextAppearance.Quantum.Light.SearchResult.Subtitle" parent="TextAppearance.Quantum.SearchResult.Subtitle" />
-
- <style name="TextAppearance.Quantum.Light.Widget" parent="TextAppearance.Widget"/>
-
- <style name="TextAppearance.Quantum.Light.Widget.Button" parent="TextAppearance.Quantum.Widget.Button" />
-
- <style name="TextAppearance.Quantum.Light.Widget.EditText" parent="TextAppearance.Quantum.Widget.EditText" />
-
- <style name="TextAppearance.Quantum.Light.Widget.Switch" parent="TextAppearance.Quantum.Small">
- <item name="textColor">@color/secondary_text_quantum_dark</item>
+ <style name="TextAppearance.Quantum.Light.TimePicker.TimeLabel" parent="TextAppearance.Quantum.TimePicker.TimeLabel">
+ <item name="textColor">@color/timepicker_default_text_color_quantum_light</item>
</style>
- <style name="TextAppearance.Quantum.Light.Widget.PopupMenu" parent="TextAppearance.Quantum.Widget.PopupMenu"/>
-
- <style name="TextAppearance.Quantum.Light.Widget.PopupMenu.Large" parent="TextAppearance.Quantum.Widget.PopupMenu.Large"/>
-
- <style name="TextAppearance.Quantum.Light.Widget.PopupMenu.Small" parent="TextAppearance.Quantum.Widget.PopupMenu.Small"/>
-
- <style name="TextAppearance.Quantum.Light.Widget.DropDownHint" parent="TextAppearance.Quantum.Widget.DropDownHint"/>
-
- <style name="TextAppearance.Quantum.Light.Widget.ActionMode.Title" parent="TextAppearance.Widget.ActionMode.Title"/>
-
- <style name="TextAppearance.Quantum.Light.Widget.ActionMode.Subtitle" parent="TextAppearance.Widget.ActionMode.Subtitle"/>
-
- <style name="TextAppearance.Quantum.Light.WindowTitle" parent="TextAppearance.Quantum.WindowTitle" />
-
- <style name="TextAppearance.Quantum.Light.DialogWindowTitle" parent="TextAppearance.Quantum.DialogWindowTitle" />
-
- <style name="TextAppearance.Quantum.Light.CalendarViewWeekDayView" parent="TextAppearance.Small.CalendarViewWeekDayView"/>
+ <style name="TextAppearance.Quantum.Light.TimePicker.AmPmLabel" parent="TextAppearance.Quantum.TimePicker.AmPmLabel">
+ <item name="textColor">@color/timepicker_default_text_color_quantum_light</item>
+ </style>
<!-- Widget Styles -->
-
- <style name="Quantum" />
- <style name="Quantum.Light" />
-
+ <style name="Quantum"/>
+ <style name="Quantum.Light"/>
<style name="Widget.Quantum" parent="Widget" />
<!-- Bordered ink button -->
<style name="Widget.Quantum.Button" parent="Widget.Button">
- <item name="background">@drawable/btn_default_quantum_dark</item>
+ <item name="background">@drawable/btn_default_quantum</item>
<item name="textAppearance">?attr/textAppearanceButton</item>
+ <item name="textColor">?attr/textColorPrimary</item>
<item name="minHeight">48dip</item>
<item name="minWidth">96dip</item>
</style>
@@ -341,12 +412,12 @@
<!-- Bordered paper button with color -->
<style name="Widget.Quantum.Button.Paper.Color">
- <item name="background">@drawable/btn_color_quantum_dark</item>
+ <item name="background">@drawable/btn_color_quantum</item>
</style>
<!-- Borderless ink button -->
<style name="Widget.Quantum.Button.Borderless">
- <item name="background">@drawable/btn_borderless_quantum_dark</item>
+ <item name="background">@drawable/btn_borderless_quantum</item>
</style>
<!-- Small borderless ink button -->
@@ -359,6 +430,7 @@
<style name="Widget.Quantum.Button.Borderless.Paper">
<!-- TODO: Specify pressed state animation. -->
</style>
+
<style name="Widget.Quantum.Button.Inset">
<item name="background">@drawable/button_inset</item>
</style>
@@ -371,26 +443,18 @@
<item name="minHeight">48dip</item>
</style>
- <style name="Quantum.ButtonBar" parent="ButtonBar">
- <item name="paddingTop">0dip</item>
- <item name="paddingStart">0dip</item>
- <item name="paddingEnd">0dip</item>
- <item name="paddingBottom">0dip</item>
- <item name="divider">?attr/dividerVertical</item>
- <item name="showDividers">middle</item>
- <item name="dividerPadding">12dip</item>
+ <style name="Widget.Quantum.ButtonBar">
<item name="background">@null</item>
</style>
- <style name="Quantum.SegmentedButton" parent="SegmentedButton">
+ <style name="Widget.Quantum.ButtonBar.AlertDialog">
+ <item name="background">@null</item>
+ </style>
+
+ <style name="Widget.Quantum.SegmentedButton" parent="SegmentedButton">
<item name="background">@drawable/btn_group_holo_dark</item>
</style>
- <style name="Quantum.ButtonBar.AlertDialog">
- <item name="background">@null</item>
- <item name="dividerPadding">0dp</item>
- </style>
-
<style name="Widget.Quantum.StackView">
<item name="resOutColor">@color/holo_blue_light</item>
<item name="clickColor">@color/holo_blue_light</item>
@@ -398,17 +462,20 @@
<style name="Widget.Quantum.TextView" parent="Widget.TextView"/>
- <style name="Widget.Quantum.CheckedTextView" parent="Widget.CheckedTextView"/>
-
<style name="Widget.Quantum.TextView.ListSeparator" parent="Widget.TextView.ListSeparator">
- <item name="background">@drawable/list_section_divider_quantum_dark</item>
+ <item name="background">@drawable/list_section_divider_quantum</item>
<item name="textAllCaps">true</item>
</style>
+ <style name="Widget.Quantum.TextView.SpinnerItem" parent="Widget.TextView.SpinnerItem">
+ <item name="textAppearance">@style/TextAppearance.Quantum.Widget.TextView.SpinnerItem</item>
+ <item name="paddingStart">8dp</item>
+ <item name="paddingEnd">8dp</item>
+ </style>
+
+ <style name="Widget.Quantum.CheckedTextView" parent="Widget.CheckedTextView"/>
<style name="Widget.Quantum.TextSelectHandle" parent="Widget.TextSelectHandle"/>
-
<style name="Widget.Quantum.TextSuggestionsPopupWindow" parent="Widget.TextSuggestionsPopupWindow"/>
-
<style name="Widget.Quantum.AbsListView" parent="Widget.AbsListView"/>
<style name="Widget.Quantum.AutoCompleteTextView" parent="Widget.AutoCompleteTextView">
@@ -417,31 +484,38 @@
</style>
<style name="Widget.Quantum.CompoundButton" parent="Widget.CompoundButton"/>
-
<style name="Widget.Quantum.CompoundButton.CheckBox" parent="Widget.CompoundButton.CheckBox"/>
+ <style name="Widget.Quantum.CompoundButton.RadioButton" parent="Widget.CompoundButton.RadioButton"/>
- <style name="Widget.Quantum.ListView.DropDown"/>
+ <style name="Widget.Quantum.CompoundButton.Star" parent="Widget.CompoundButton.Star">
+ <item name="button">@drawable/btn_star_quantum</item>
+ </style>
+
+ <style name="Widget.Quantum.CompoundButton.Switch">
+ <item name="track">@drawable/switch_track_quantum</item>
+ <item name="thumb">@drawable/switch_inner_quantum</item>
+ <item name="switchTextAppearance">@style/TextAppearance.Quantum.Widget.Switch</item>
+ <item name="textOn"></item>
+ <item name="textOff"></item>
+ <item name="thumbTextPadding">12dip</item>
+ <item name="switchMinWidth">72dip</item>
+ <item name="switchPadding">16dip</item>
+ </style>
<style name="Widget.Quantum.EditText" parent="Widget.EditText"/>
<style name="Widget.Quantum.ExpandableListView" parent="Widget.Quantum.ListView">
- <item name="groupIndicator">@drawable/expander_group_quantum_dark</item>
+ <item name="groupIndicator">@drawable/expander_group_quantum</item>
<item name="indicatorLeft">?attr/expandableListPreferredItemIndicatorLeft</item>
<item name="indicatorRight">?attr/expandableListPreferredItemIndicatorRight</item>
<item name="childDivider">?attr/listDivider</item>
</style>
<style name="Widget.Quantum.ExpandableListView.White"/>
-
<style name="Widget.Quantum.FragmentBreadCrumbs" parent="Widget.FragmentBreadCrumbs"/>
-
<style name="Widget.Quantum.Gallery" parent="Widget.Gallery"/>
-
<style name="Widget.Quantum.GestureOverlayView" parent="Widget.GestureOverlayView"/>
-
- <style name="Widget.Quantum.GridView" parent="Widget.GridView">
- <item name="listSelector">?attr/selectableItemBackground</item>
- </style>
+ <style name="Widget.Quantum.GridView" parent="Widget.GridView"/>
<style name="Widget.Quantum.CalendarView" parent="Widget.CalendarView">
<item name="selectedWeekBackgroundColor">#330099FF</item>
@@ -454,7 +528,7 @@
</style>
<style name="Widget.Quantum.ImageButton" parent="Widget.ImageButton">
- <item name="background">@drawable/btn_default_quantum_dark</item>
+ <item name="background">@drawable/btn_default_quantum</item>
</style>
<style name="Widget.Quantum.NumberPicker" parent="Widget.NumberPicker">
@@ -489,7 +563,6 @@
</style>
<style name="Widget.Quantum.ActivityChooserView" parent="Widget.ActivityChooserView"/>
-
<style name="Widget.Quantum.ImageWell" parent="Widget.ImageWell"/>
<style name="Widget.Quantum.ListView" parent="Widget.ListView">
@@ -497,6 +570,7 @@
<item name="listSelector">?attr/listChoiceBackgroundIndicator</item>
</style>
+ <style name="Widget.Quantum.ListView.DropDown"/>
<style name="Widget.Quantum.ListView.White"/>
<style name="Widget.Quantum.PopupWindow" parent="Widget.PopupWindow"/>
@@ -510,8 +584,10 @@
<item name="indeterminateDrawable">@drawable/progress_medium_holo</item>
</style>
+ <style name="Widget.Quantum.ProgressBar.Inverse"/>
+
<style name="Widget.Quantum.ProgressBar.Horizontal" parent="Widget.ProgressBar.Horizontal">
- <item name="progressDrawable">@drawable/progress_horizontal_quantum_dark</item>
+ <item name="progressDrawable">@drawable/progress_horizontal_quantum</item>
<item name="indeterminateDrawable">@drawable/progress_indeterminate_horizontal_holo</item>
<item name="minHeight">16dip</item>
<item name="maxHeight">16dip</item>
@@ -521,25 +597,22 @@
<item name="indeterminateDrawable">@drawable/progress_small_holo</item>
</style>
+ <style name="Widget.Quantum.ProgressBar.Small.Inverse"/>
<style name="Widget.Quantum.ProgressBar.Small.Title"/>
<style name="Widget.Quantum.ProgressBar.Large" parent="Widget.ProgressBar.Large">
<item name="indeterminateDrawable">@drawable/progress_large_holo</item>
</style>
- <style name="Widget.Quantum.ProgressBar.Inverse"/>
-
- <style name="Widget.Quantum.ProgressBar.Small.Inverse"/>
-
<style name="Widget.Quantum.ProgressBar.Large.Inverse"/>
<style name="Widget.Quantum.SeekBar">
<item name="indeterminateOnly">false</item>
- <item name="progressDrawable">@drawable/scrubber_progress_horizontal_quantum_dark</item>
- <item name="indeterminateDrawable">@drawable/scrubber_progress_horizontal_quantum_dark</item>
+ <item name="progressDrawable">@drawable/scrubber_progress_horizontal_quantum</item>
+ <item name="indeterminateDrawable">@drawable/scrubber_progress_horizontal_quantum</item>
<item name="minHeight">13dip</item>
<item name="maxHeight">13dip</item>
- <item name="thumb">@drawable/scrubber_control_selector_quantum_dark</item>
+ <item name="thumb">@drawable/scrubber_control_selector_quantum</item>
<item name="thumbOffset">16dip</item>
<item name="focusable">true</item>
<item name="paddingStart">16dip</item>
@@ -548,8 +621,8 @@
</style>
<style name="Widget.Quantum.RatingBar" parent="Widget.RatingBar">
- <item name="progressDrawable">@drawable/ratingbar_full_holo_dark</item>
- <item name="indeterminateDrawable">@drawable/ratingbar_full_holo_dark</item>
+ <item name="progressDrawable">@drawable/ratingbar_full_quantum</item>
+ <item name="indeterminateDrawable">@drawable/ratingbar_full_quantum</item>
</style>
<style name="Widget.Quantum.RatingBar.Indicator" parent="Widget.RatingBar.Indicator">
@@ -566,14 +639,11 @@
<item name="maxHeight">16dip</item>
</style>
- <style name="Widget.Quantum.CompoundButton.RadioButton" parent="Widget.CompoundButton.RadioButton"/>
-
<style name="Widget.Quantum.ScrollView" parent="Widget.ScrollView"/>
-
<style name="Widget.Quantum.HorizontalScrollView" parent="Widget.HorizontalScrollView"/>
<style name="Widget.Quantum.Spinner" parent="Widget.Spinner.DropDown">
- <item name="background">@drawable/spinner_background_quantum_dark</item>
+ <item name="background">@drawable/spinner_background_quantum</item>
<item name="dropDownSelector">@drawable/list_selector_holo_dark</item>
<item name="popupBackground">?attr/colorBackground</item>
<item name="dropDownVerticalOffset">0dip</item>
@@ -587,11 +657,7 @@
<style name="Widget.Quantum.Spinner.DropDown"/>
<style name="Widget.Quantum.Spinner.DropDown.ActionBar">
- <item name="background">@drawable/spinner_background_quantum_dark</item>
- </style>
-
- <style name="Widget.Quantum.CompoundButton.Star" parent="Widget.CompoundButton.Star">
- <item name="button">@drawable/btn_star_quantum_dark</item>
+ <item name="background">@drawable/spinner_background_quantum</item>
</style>
<style name="Widget.Quantum.TabWidget" parent="Widget.TabWidget">
@@ -602,11 +668,11 @@
<item name="showDividers">middle</item>
<item name="dividerPadding">8dip</item>
<item name="measureWithLargestChild">true</item>
- <item name="tabLayout">@layout/tab_indicator_holo</item>
+ <item name="tabLayout">@layout/tab_indicator_quantum</item>
</style>
<style name="Widget.Quantum.Tab" parent="Widget.Quantum.ActionBar.TabView">
- <item name="background">@drawable/tab_indicator_quantum_dark</item>
+ <item name="background">@drawable/tab_indicator_quantum</item>
<item name="layout_width">0dip</item>
<item name="layout_weight">1</item>
<item name="minWidth">80dip</item>
@@ -628,24 +694,12 @@
<style name="Widget.Quantum.DropDownItem.Spinner"/>
- <style name="Widget.Quantum.TextView.SpinnerItem" parent="Widget.TextView.SpinnerItem">
- <item name="textAppearance">@style/TextAppearance.Quantum.Widget.TextView.SpinnerItem</item>
- <item name="paddingStart">8dp</item>
- <item name="paddingEnd">8dp</item>
- </style>
-
<style name="Widget.Quantum.KeyboardView" parent="Widget.KeyboardView"/>
-
<style name="Widget.Quantum.QuickContactBadge.WindowSmall" parent="Widget.QuickContactBadge.WindowSmall"/>
-
<style name="Widget.Quantum.QuickContactBadge.WindowMedium" parent="Widget.QuickContactBadge.WindowMedium"/>
-
<style name="Widget.Quantum.QuickContactBadge.WindowLarge" parent="Widget.QuickContactBadge.WindowLarge"/>
-
<style name="Widget.Quantum.QuickContactBadgeSmall.WindowSmall" parent="Widget.QuickContactBadgeSmall.WindowSmall"/>
-
<style name="Widget.Quantum.QuickContactBadgeSmall.WindowMedium" parent="Widget.QuickContactBadgeSmall.WindowMedium"/>
-
<style name="Widget.Quantum.QuickContactBadgeSmall.WindowLarge" parent="Widget.QuickContactBadgeSmall.WindowLarge"/>
<style name="Widget.Quantum.ListPopupWindow" parent="Widget.ListPopupWindow">
@@ -658,12 +712,6 @@
<style name="Widget.Quantum.PopupMenu" parent="Widget.Quantum.ListPopupWindow"/>
- <style name="Widget.Quantum.ButtonBar">
- <item name="divider">?attr/dividerVertical</item>
- </style>
-
- <style name="Widget.Quantum.ButtonBar.Button"/>
-
<style name="Widget.Quantum.ActionButton" parent="Widget.ActionButton">
<item name="minWidth">@dimen/action_button_min_width</item>
<item name="gravity">center</item>
@@ -673,16 +721,20 @@
<item name="maxLines">2</item>
</style>
+ <style name="Widget.Quantum.ActionButton.CloseMode">
+ <item name="background">@drawable/btn_cab_done_quantum</item>
+ </style>
+
<style name="Widget.Quantum.ActionButton.Overflow">
- <item name="src">@drawable/ic_menu_moreoverflow_quantum_dark</item>
+ <item name="src">@drawable/ic_menu_moreoverflow_quantum</item>
<item name="background">?attr/actionBarItemBackground</item>
<item name="contentDescription">@string/action_menu_overflow_description</item>
</style>
- <style name="Widget.Quantum.ActionButton.TextButton" parent="Widget.Quantum.ButtonBar.Button"/>
+ <style name="Widget.Quantum.ActionButton.TextButton" parent="Widget.Quantum.ButtonBar"/>
<style name="Widget.Quantum.ActionBar.TabView" parent="Widget.ActionBar.TabView">
- <item name="background">@drawable/tab_indicator_quantum_dark</item>
+ <item name="background">@drawable/tab_indicator_quantum</item>
<item name="paddingStart">16dip</item>
<item name="paddingEnd">16dip</item>
</style>
@@ -703,21 +755,12 @@
<item name="maxLines">2</item>
</style>
- <style name="Widget.Quantum.ActionMode" parent="Widget.ActionMode">
- <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionMode.Title</item>
- <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionMode.Subtitle</item>
- </style>
-
- <style name="Widget.Quantum.ActionButton.CloseMode">
- <item name="background">@drawable/btn_cab_done_holo_dark</item>
- </style>
-
<style name="Widget.Quantum.ActionBar" parent="Widget.ActionBar">
<item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
<item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
- <item name="background">@drawable/ab_transparent_quantum_dark</item>
- <item name="backgroundStacked">@drawable/ab_stacked_transparent_dark_holo</item>
- <item name="backgroundSplit">@drawable/ab_bottom_transparent_dark_holo</item>
+ <item name="background">@drawable/ab_transparent_quantum</item>
+ <item name="backgroundStacked">@drawable/ab_stacked_transparent_quantum</item>
+ <item name="backgroundSplit">@drawable/ab_bottom_transparent_quantum</item>
<item name="divider">?attr/dividerVertical</item>
<item name="progressBarStyle">@style/Widget.Quantum.ProgressBar.Horizontal</item>
<item name="indeterminateProgressStyle">@style/Widget.Quantum.ProgressBar</item>
@@ -728,9 +771,9 @@
<style name="Widget.Quantum.ActionBar.Solid">
<item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
<item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
- <item name="background">@drawable/ab_solid_dark_holo</item>
- <item name="backgroundStacked">@drawable/ab_stacked_solid_dark_holo</item>
- <item name="backgroundSplit">@drawable/ab_bottom_solid_dark_holo</item>
+ <item name="background">@drawable/ab_solid_quantum</item>
+ <item name="backgroundStacked">@drawable/ab_stacked_solid_quantum</item>
+ <item name="backgroundSplit">@drawable/ab_bottom_solid_quantum</item>
<item name="divider">?attr/dividerVertical</item>
<item name="progressBarStyle">@style/Widget.Quantum.ProgressBar.Horizontal</item>
<item name="indeterminateProgressStyle">@style/Widget.Quantum.ProgressBar</item>
@@ -738,61 +781,43 @@
<item name="itemPadding">8dip</item>
</style>
- <style name="Widget.Quantum.CompoundButton.Switch">
- <item name="track">@drawable/switch_track_quantum_dark</item>
- <item name="thumb">@drawable/switch_inner_quantum_dark</item>
- <item name="switchTextAppearance">@style/TextAppearance.Quantum.Widget.Switch</item>
- <item name="textOn"></item>
- <item name="textOff"></item>
- <item name="thumbTextPadding">12dip</item>
- <item name="switchMinWidth">72dip</item>
- <item name="switchPadding">16dip</item>
+ <style name="Widget.Quantum.ActionMode" parent="Widget.ActionMode">
+ <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionMode.Title</item>
+ <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionMode.Subtitle</item>
+ </style>
+
+ <style name="Widget.Quantum.FastScroll" parent="Widget.FastScroll">
+ <item name="thumbMinWidth">0dp</item>
+ <item name="thumbMinHeight">0dp</item>
+ </style>
+
+ <style name="Widget.Quantum.PreferenceFrameLayout">
+ <item name="borderTop">0dip</item>
+ <item name="borderBottom">@dimen/preference_fragment_padding_bottom</item>
+ <item name="borderLeft">?attr/preferenceFragmentPaddingSide</item>
+ <item name="borderRight">?attr/preferenceFragmentPaddingSide</item>
+ </style>
+
+ <style name="Widget.Quantum.MediaRouteButton">
+ <item name="background">?attr/selectableItemBackground</item>
+ <item name="externalRouteEnabledDrawable">@drawable/ic_media_route_quantum</item>
+ <item name="minWidth">56dp</item>
+ <item name="minHeight">48dp</item>
+ <item name="focusable">true</item>
+ <item name="contentDescription">@string/media_route_button_content_description</item>
</style>
<!-- Light widget styles -->
- <style name="Widget.Quantum.Light" parent="Widget" />
-
- <!-- Bordered ink button -->
- <style name="Widget.Quantum.Light.Button" parent="Widget.Quantum.Button">
- <item name="background">@drawable/btn_default_quantum_light</item>
- <item name="textAppearance">?attr/textAppearanceButton</item>
- <item name="minHeight">48dip</item>
- <item name="minWidth">96dip</item>
- </style>
-
- <!-- Small bordered ink button -->
- <style name="Widget.Quantum.Light.Button.Small">
- <item name="minHeight">48dip</item>
- <item name="minWidth">48dip</item>
- </style>
-
- <!-- Bordered paper button -->
- <style name="Widget.Quantum.Light.Button.Paper">
- <!-- TODO: Specify pressed state animation. -->
- </style>
-
- <!-- Bordered paper button with color -->
- <style name="Widget.Quantum.Light.Button.Paper.Color">
- <item name="background">@drawable/btn_color_quantum_light</item>
- </style>
-
- <!-- Borderless ink button -->
- <style name="Widget.Quantum.Light.Button.Borderless">
- <item name="background">@drawable/btn_borderless_quantum_light</item>
- </style>
-
- <!-- Small borderless ink button -->
- <style name="Widget.Quantum.Light.Button.Borderless.Small">
- <item name="minHeight">48dip</item>
- <item name="minWidth">48dip</item>
- </style>
-
- <!-- Borderless paper button -->
- <style name="Widget.Quantum.Light.Button.Borderless.Paper">
- <!-- TODO: Specify pressed state animation. -->
- </style>
- <style name="Widget.Quantum.Light.Button.Inset"/>
+ <style name="Widget.Quantum.Light" parent="Widget.Quantum"/>
+ <style name="Widget.Quantum.Light.Button" parent="Widget.Quantum.Button"/>
+ <style name="Widget.Quantum.Light.Button.Small" parent="Widget.Quantum.Button.Small"/>
+ <style name="Widget.Quantum.Light.Button.Paper" parent="Widget.Quantum.Button.Paper"/>
+ <style name="Widget.Quantum.Light.Button.Paper.Color" parent="Widget.Quantum.Button.Paper.Color"/>
+ <style name="Widget.Quantum.Light.Button.Borderless" parent="Widget.Quantum.Button.Borderless"/>
+ <style name="Widget.Quantum.Light.Button.Borderless.Small" parent="Widget.Quantum.Button.Borderless.Small"/>
+ <style name="Widget.Quantum.Light.Button.Borderless.Paper" parent="Widget.Quantum.Button.Borderless.Paper"/>
+ <style name="Widget.Quantum.Light.Button.Inset" parent="Widget.Quantum.Button.Inset"/>
<style name="Widget.Quantum.Light.Button.Toggle">
<item name="background">@drawable/btn_toggle_holo_light</item>
@@ -802,63 +827,36 @@
<item name="minHeight">48dip</item>
</style>
- <style name="Quantum.Light.ButtonBar" parent="Quantum.ButtonBar"/>
+ <style name="Widget.Quantum.Light.ButtonBar" parent="Widget.Quantum.ButtonBar"/>
+ <style name="Widget.Quantum.Light.ButtonBar.AlertDialog" parent="Widget.Quantum.ButtonBar.AlertDialog"/>
- <style name="Quantum.Light.ButtonBar.AlertDialog">
- <item name="background">@null</item>
- <item name="dividerPadding">0dp</item>
- </style>
-
- <style name="Quantum.Light.SegmentedButton" parent="SegmentedButton">
+ <style name="Widget.Quantum.Light.SegmentedButton" parent="Widget.Quantum.SegmentedButton">
<item name="background">@drawable/btn_group_holo_light</item>
</style>
- <style name="Widget.Quantum.Light.TextView" parent="Widget.TextView"/>
-
- <style name="Widget.Quantum.Light.CheckedTextView" parent="Widget.CheckedTextView"/>
-
- <style name="Widget.Quantum.Light.TextView.ListSeparator" parent="Widget.TextView.ListSeparator">
- <item name="background">@drawable/list_section_divider_quantum_light</item>
- <item name="textAllCaps">true</item>
- </style>
-
- <style name="Widget.Quantum.Light.TextSelectHandle" parent="Widget.TextSelectHandle"/>
-
- <style name="Widget.Quantum.Light.TextSuggestionsPopupWindow" parent="Widget.TextSuggestionsPopupWindow"/>
-
- <style name="Widget.Quantum.Light.AbsListView" parent="Widget.AbsListView"/>
+ <style name="Widget.Quantum.Light.TextView" parent="Widget.Quantum.TextView"/>
+ <style name="Widget.Quantum.Light.TextView.ListSeparator" parent="Widget.Quantum.TextView.ListSeparator"/>
+ <style name="Widget.Quantum.Light.TextView.SpinnerItem" parent="Widget.Quantum.TextView.SpinnerItem"/>
+ <style name="Widget.Quantum.Light.CheckedTextView" parent="Widget.Quantum.CheckedTextView"/>
+ <style name="Widget.Quantum.Light.TextSelectHandle" parent="Widget.Quantum.TextSelectHandle"/>
+ <style name="Widget.Quantum.Light.TextSuggestionsPopupWindow" parent="Widget.Quantum.TextSuggestionsPopupWindow"/>
+ <style name="Widget.Quantum.Light.AbsListView" parent="Widget.Quantum.AbsListView"/>
<style name="Widget.Quantum.Light.AutoCompleteTextView" parent="Widget.AutoCompleteTextView">
<item name="dropDownSelector">@drawable/list_selector_holo_light</item>
<item name="popupBackground">?attr/colorBackground</item>
</style>
- <style name="Widget.Quantum.Light.CompoundButton.CheckBox" parent="Widget.CompoundButton.CheckBox"/>
-
- <style name="Widget.Quantum.Light.ListView.DropDown"/>
-
+ <style name="Widget.Quantum.Light.CompoundButton.CheckBox" parent="Widget.Quantum.CompoundButton.CheckBox"/>
+ <style name="Widget.Quantum.Light.ListView.DropDown" parent="Widget.Quantum.ListView.DropDown"/>
<style name="Widget.Quantum.Light.EditText" parent="Widget.Quantum.EditText"/>
-
- <style name="Widget.Quantum.Light.ExpandableListView" parent="Widget.Quantum.Light.ListView">
- <item name="groupIndicator">@drawable/expander_group_quantum_light</item>
- <item name="indicatorLeft">?attr/expandableListPreferredItemIndicatorLeft</item>
- <item name="indicatorRight">?attr/expandableListPreferredItemIndicatorRight</item>
- <item name="childDivider">?attr/listDivider</item>
- </style>
-
- <style name="Widget.Quantum.Light.ExpandableListView.White"/>
-
- <style name="Widget.Quantum.Light.FragmentBreadCrumbs" parent="Widget.FragmentBreadCrumbs"/>
-
- <style name="Widget.Quantum.Light.Gallery" parent="Widget.Gallery"/>
-
- <style name="Widget.Quantum.Light.GestureOverlayView" parent="Widget.GestureOverlayView"/>
-
+ <style name="Widget.Quantum.Light.ExpandableListView" parent="Widget.Quantum.ExpandableListView"/>
+ <style name="Widget.Quantum.Light.ExpandableListView.White" parent="Widget.Quantum.ExpandableListView.White"/>
+ <style name="Widget.Quantum.Light.FragmentBreadCrumbs" parent="Widget.Quantum.FragmentBreadCrumbs"/>
+ <style name="Widget.Quantum.Light.Gallery" parent="Widget.Quantum.Gallery"/>
+ <style name="Widget.Quantum.Light.GestureOverlayView" parent="Widget.Quantum.GestureOverlayView"/>
<style name="Widget.Quantum.Light.GridView" parent="Widget.Quantum.GridView"/>
-
- <style name="Widget.Quantum.Light.ImageButton" parent="Widget.Quantum.ImageButton">
- <item name="background">@drawable/btn_default_quantum_light</item>
- </style>
+ <style name="Widget.Quantum.Light.ImageButton" parent="Widget.Quantum.ImageButton"/>
<style name="Widget.Quantum.Light.CalendarView" parent="Widget.CalendarView">
<item name="selectedWeekBackgroundColor">#330066ff</item>
@@ -889,16 +887,13 @@
<style name="Widget.Quantum.Light.DatePicker" parent="Widget.Quantum.DatePicker"/>
<style name="Widget.Quantum.Light.ActivityChooserView" parent="Widget.Quantum.ActivityChooserView">
- <item name="background">@drawable/ab_share_pack_holo_light</item>
+ <item name="background">@drawable/ab_share_pack_quantum</item>
</style>
- <style name="Widget.Quantum.Light.ImageWell" parent="Widget.ImageWell"/>
-
+ <style name="Widget.Quantum.Light.ImageWell" parent="Widget.Quantum.ImageWell"/>
<style name="Widget.Quantum.Light.ListView" parent="Widget.Quantum.ListView"/>
-
- <style name="Widget.Quantum.Light.ListView.White"/>
-
- <style name="Widget.Quantum.Light.PopupWindow" parent="Widget.PopupWindow"/>
+ <style name="Widget.Quantum.Light.ListView.White" parent="Widget.Quantum.ListView.White"/>
+ <style name="Widget.Quantum.Light.PopupWindow" parent="Widget.Quantum.PopupWindow"/>
<style name="Widget.Quantum.Light.PopupWindow.ActionMode">
<item name="popupBackground">@color/white</item>
@@ -906,33 +901,16 @@
</style>
<style name="Widget.Quantum.Light.ProgressBar" parent="Widget.Quantum.ProgressBar"/>
-
- <style name="Widget.Quantum.Light.ProgressBar.Horizontal" parent="Widget.Quantum.ProgressBar.Horizontal">
- <item name="progressDrawable">@drawable/progress_horizontal_quantum_light</item>
- </style>
-
+ <style name="Widget.Quantum.Light.ProgressBar.Horizontal" parent="Widget.Quantum.ProgressBar.Horizontal"/>
<style name="Widget.Quantum.Light.ProgressBar.Small" parent="Widget.Quantum.ProgressBar.Small"/>
-
<style name="Widget.Quantum.Light.ProgressBar.Small.Title" parent="Widget.Quantum.ProgressBar.Small.Title"/>
-
<style name="Widget.Quantum.Light.ProgressBar.Large" parent="Widget.Quantum.ProgressBar.Large"/>
-
<style name="Widget.Quantum.Light.ProgressBar.Inverse" parent="Widget.Quantum.ProgressBar.Inverse"/>
-
<style name="Widget.Quantum.Light.ProgressBar.Small.Inverse" parent="Widget.Quantum.ProgressBar.Small.Inverse"/>
-
<style name="Widget.Quantum.Light.ProgressBar.Large.Inverse" parent="Widget.Quantum.ProgressBar.Large.Inverse"/>
+ <style name="Widget.Quantum.Light.SeekBar" parent="Widget.Quantum.SeekBar"/>
- <style name="Widget.Quantum.Light.SeekBar" parent="Widget.Quantum.SeekBar">
- <item name="progressDrawable">@drawable/scrubber_progress_horizontal_quantum_light</item>
- <item name="indeterminateDrawable">@drawable/scrubber_progress_horizontal_quantum_light</item>
- <item name="thumb">@drawable/scrubber_control_selector_quantum_light</item>
- </style>
-
- <style name="Widget.Quantum.Light.RatingBar" parent="Widget.RatingBar">
- <item name="progressDrawable">@drawable/ratingbar_full_holo_light</item>
- <item name="indeterminateDrawable">@drawable/ratingbar_full_holo_light</item>
- </style>
+ <style name="Widget.Quantum.Light.RatingBar" parent="Widget.Quantum.RatingBar" />
<style name="Widget.Quantum.Light.RatingBar.Indicator" parent="Widget.RatingBar.Indicator">
<item name="progressDrawable">@drawable/ratingbar_holo_light</item>
@@ -948,14 +926,12 @@
<item name="maxHeight">16dip</item>
</style>
- <style name="Widget.Quantum.Light.CompoundButton.RadioButton" parent="Widget.CompoundButton.RadioButton"/>
-
- <style name="Widget.Quantum.Light.ScrollView" parent="Widget.ScrollView"/>
-
- <style name="Widget.Quantum.Light.HorizontalScrollView" parent="Widget.HorizontalScrollView"/>
+ <style name="Widget.Quantum.Light.CompoundButton.RadioButton" parent="Widget.Quantum.CompoundButton.RadioButton"/>
+ <style name="Widget.Quantum.Light.ScrollView" parent="Widget.Quantum.ScrollView"/>
+ <style name="Widget.Quantum.Light.HorizontalScrollView" parent="Widget.Quantum.HorizontalScrollView"/>
<style name="Widget.Quantum.Light.Spinner" parent="Widget.Quantum.Spinner">
- <item name="background">@drawable/spinner_background_quantum_light</item>
+ <item name="background">@drawable/spinner_background_quantum</item>
<item name="dropDownSelector">@drawable/list_selector_holo_light</item>
<item name="popupBackground">?attr/colorBackground</item>
<item name="dropDownVerticalOffset">0dip</item>
@@ -964,41 +940,21 @@
<item name="popupPromptView">@layout/simple_dropdown_hint</item>
</style>
- <style name="Widget.Quantum.Light.Spinner.DropDown"/>
-
- <style name="Widget.Quantum.Light.Spinner.DropDown.ActionBar">
- <item name="background">@drawable/spinner_background_quantum_light</item>
- </style>
-
- <style name="Widget.Quantum.Light.CompoundButton.Star" parent="Widget.CompoundButton.Star">
- <item name="button">@drawable/btn_star_quantum_light</item>
- </style>
-
+ <style name="Widget.Quantum.Light.Spinner.DropDown" parent="Widget.Quantum.Spinner.DropDown"/>
+ <style name="Widget.Quantum.Light.Spinner.DropDown.ActionBar" parent="Widget.Quantum.Spinner.DropDown.ActionBar"/>
+ <style name="Widget.Quantum.Light.CompoundButton.Star" parent="Widget.Quantum.CompoundButton.Star"/>
<style name="Widget.Quantum.Light.TabWidget" parent="Widget.Quantum.TabWidget"/>
-
- <style name="Widget.Quantum.Light.WebTextView" parent="Widget.WebTextView"/>
-
- <style name="Widget.Quantum.Light.WebView" parent="Widget.WebView"/>
-
+ <style name="Widget.Quantum.Light.WebTextView" parent="Widget.Quantum.WebTextView"/>
+ <style name="Widget.Quantum.Light.WebView" parent="Widget.Quantum.WebView"/>
<style name="Widget.Quantum.Light.DropDownItem" parent="Widget.Quantum.DropDownItem"/>
-
- <style name="Widget.Quantum.Light.DropDownItem.Spinner"/>
-
- <style name="Widget.Quantum.Light.TextView.SpinnerItem" parent="Widget.Quantum.TextView.SpinnerItem"/>
-
- <style name="Widget.Quantum.Light.KeyboardView" parent="Widget.KeyboardView"/>
-
- <style name="Widget.Quantum.Light.QuickContactBadge.WindowSmall" parent="Widget.QuickContactBadge.WindowSmall"/>
-
- <style name="Widget.Quantum.Light.QuickContactBadge.WindowMedium" parent="Widget.QuickContactBadge.WindowMedium"/>
-
- <style name="Widget.Quantum.Light.QuickContactBadge.WindowLarge" parent="Widget.QuickContactBadge.WindowLarge"/>
-
- <style name="Widget.Quantum.Light.QuickContactBadgeSmall.WindowSmall" parent="Widget.QuickContactBadgeSmall.WindowSmall"/>
-
- <style name="Widget.Quantum.Light.QuickContactBadgeSmall.WindowMedium" parent="Widget.QuickContactBadgeSmall.WindowMedium"/>
-
- <style name="Widget.Quantum.Light.QuickContactBadgeSmall.WindowLarge" parent="Widget.QuickContactBadgeSmall.WindowLarge"/>
+ <style name="Widget.Quantum.Light.DropDownItem.Spinner" parent="Widget.Quantum.DropDownItem.Spinner"/>
+ <style name="Widget.Quantum.Light.KeyboardView" parent="Widget.Quantum.KeyboardView"/>
+ <style name="Widget.Quantum.Light.QuickContactBadge.WindowSmall" parent="Widget.Quantum.QuickContactBadge.WindowSmall"/>
+ <style name="Widget.Quantum.Light.QuickContactBadge.WindowMedium" parent="Widget.Quantum.QuickContactBadge.WindowMedium"/>
+ <style name="Widget.Quantum.Light.QuickContactBadge.WindowLarge" parent="Widget.Quantum.QuickContactBadge.WindowLarge"/>
+ <style name="Widget.Quantum.Light.QuickContactBadgeSmall.WindowSmall" parent="Widget.Quantum.QuickContactBadgeSmall.WindowSmall"/>
+ <style name="Widget.Quantum.Light.QuickContactBadgeSmall.WindowMedium" parent="Widget.Quantum.QuickContactBadgeSmall.WindowMedium"/>
+ <style name="Widget.Quantum.Light.QuickContactBadgeSmall.WindowLarge" parent="Widget.Quantum.QuickContactBadgeSmall.WindowLarge"/>
<style name="Widget.Quantum.Light.ListPopupWindow" parent="Widget.ListPopupWindow">
<item name="dropDownSelector">@drawable/list_selector_holo_light</item>
@@ -1011,55 +967,28 @@
<style name="Widget.Quantum.Light.PopupMenu" parent="Widget.Quantum.Light.ListPopupWindow"/>
<style name="Widget.Quantum.Light.ActionButton" parent="Widget.Quantum.ActionButton"/>
-
- <style name="Widget.Quantum.Light.ActionButton.Overflow">
- <item name="src">@drawable/ic_menu_moreoverflow_quantum_light</item>
- <item name="contentDescription">@string/action_menu_overflow_description</item>
- </style>
-
- <style name="Widget.Quantum.Light.ActionBar.TabView" parent="Widget.Quantum.ActionBar.TabView">
- <item name="background">@drawable/tab_indicator_quantum_light</item>
- </style>
-
- <style name="Widget.Quantum.Light.Tab" parent="Widget.Quantum.Light.ActionBar.TabView">
- <item name="layout_width">0dip</item>
- <item name="layout_weight">1</item>
- <item name="minWidth">80dip</item>
- </style>
-
+ <style name="Widget.Quantum.Light.ActionButton.Overflow" parent="Widget.Quantum.ActionButton.Overflow"/>
+ <style name="Widget.Quantum.Light.Tab" parent="Widget.Quantum.Tab"/>
+ <style name="Widget.Quantum.Light.ActionBar.TabView" parent="Widget.Quantum.ActionBar.TabView"/>
<style name="Widget.Quantum.Light.ActionBar.TabBar" parent="Widget.Quantum.ActionBar.TabBar"/>
-
<style name="Widget.Quantum.Light.ActionBar.TabText" parent="Widget.Quantum.ActionBar.TabText"/>
- <style name="Widget.Quantum.Light.ActionBar.TabView.Inverse"/>
-
- <style name="Widget.Quantum.Light.ActionBar.TabBar.Inverse"/>
-
- <style name="Widget.Quantum.Light.ActionBar.TabText.Inverse">
- <item name="textColor">?attr/textColorPrimaryInverse</item>
- </style>
-
<style name="Widget.Quantum.Light.ActionMode" parent="Widget.Quantum.ActionMode">
<item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionMode.Title</item>
<item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionMode.Subtitle</item>
</style>
- <style name="Widget.Quantum.Light.ActionMode.Inverse" parent="Widget.ActionMode">
- <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionMode.Title.Inverse</item>
- <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionMode.Subtitle.Inverse</item>
- </style>
-
<style name="Widget.Quantum.Light.ActionButton.CloseMode">
- <item name="background">@drawable/btn_cab_done_holo_light</item>
+ <item name="background">@drawable/btn_cab_done_quantum</item>
</style>
<style name="Widget.Quantum.Light.ActionBar" parent="Widget.Quantum.ActionBar">
<item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
<item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
- <item name="background">@drawable/ab_transparent_quantum_light</item>
- <item name="backgroundStacked">@drawable/ab_stacked_transparent_light_holo</item>
- <item name="backgroundSplit">@drawable/ab_bottom_transparent_light_holo</item>
- <item name="homeAsUpIndicator">@drawable/ic_ab_back_quantum_light</item>
+ <item name="background">@drawable/ab_transparent_quantum</item>
+ <item name="backgroundStacked">@drawable/ab_stacked_transparent_quantum</item>
+ <item name="backgroundSplit">@drawable/ab_bottom_transparent_quantum</item>
+ <item name="homeAsUpIndicator">@drawable/ic_ab_back_quantum</item>
<item name="progressBarStyle">@style/Widget.Quantum.Light.ProgressBar.Horizontal</item>
<item name="indeterminateProgressStyle">@style/Widget.Quantum.Light.ProgressBar</item>
</style>
@@ -1067,9 +996,9 @@
<style name="Widget.Quantum.Light.ActionBar.Solid">
<item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
<item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
- <item name="background">@drawable/ab_solid_light_holo</item>
- <item name="backgroundStacked">@drawable/ab_stacked_solid_light_holo</item>
- <item name="backgroundSplit">@drawable/ab_bottom_solid_light_holo</item>
+ <item name="background">@drawable/ab_solid_quantum</item>
+ <item name="backgroundStacked">@drawable/ab_stacked_solid_quantum</item>
+ <item name="backgroundSplit">@drawable/ab_bottom_solid_quantum</item>
<item name="divider">?attr/dividerVertical</item>
<item name="progressBarStyle">@style/Widget.Quantum.Light.ProgressBar.Horizontal</item>
<item name="indeterminateProgressStyle">@style/Widget.Quantum.Light.ProgressBar</item>
@@ -1077,36 +1006,20 @@
<item name="itemPadding">8dip</item>
</style>
- <style name="Widget.Quantum.Light.ActionBar.Solid.Inverse">
- <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title.Inverse</item>
- <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle.Inverse</item>
- <item name="background">@drawable/ab_solid_dark_holo</item>
- <item name="backgroundStacked">@drawable/ab_stacked_solid_dark_holo</item>
- <item name="backgroundSplit">@drawable/ab_bottom_solid_inverse_holo</item>
- <item name="divider">@drawable/list_divider_quantum_dark</item>
- <item name="progressBarStyle">@style/Widget.Quantum.ProgressBar.Horizontal</item>
- <item name="indeterminateProgressStyle">@style/Widget.Quantum.ProgressBar</item>
- <item name="progressBarPadding">32dip</item>
- <item name="itemPadding">8dip</item>
+ <style name="Widget.Quantum.Light.CompoundButton.Switch" parent="Widget.Quantum.CompoundButton.Switch">
+ <item name="switchTextAppearance">@style/TextAppearance.Quantum.Light.Widget.Switch</item>
</style>
- <style name="Widget.Quantum.Light.CompoundButton.Switch" parent="Widget.CompoundButton.Switch">
- <item name="track">@drawable/switch_track_quantum_light</item>
- <item name="thumb">@drawable/switch_inner_quantum_light</item>
- <item name="switchTextAppearance">@style/TextAppearance.Quantum.Light.Widget.Switch</item>
- <item name="textOn"></item>
- <item name="textOff"></item>
- <item name="thumbTextPadding">12dip</item>
- <item name="switchMinWidth">96dip</item>
- <item name="switchPadding">16dip</item>
+ <style name="Widget.Quantum.Light.FastScroll" parent="Widget.Quantum.FastScroll"/>
+
+ <style name="Widget.Quantum.Light.MediaRouteButton" parent="Widget.Quantum.MediaRouteButton">
+ <item name="externalRouteEnabledDrawable">@drawable/ic_media_route_quantum</item>
</style>
<!-- Animation Styles -->
<style name="Animation.Quantum" parent="Animation"/>
-
<style name="Animation.Quantum.Activity" parent="Animation.Activity"/>
-
<style name="Animation.Quantum.Dialog" parent="Animation.Dialog"/>
<!-- Dialog styles -->
@@ -1122,16 +1035,16 @@
<item name="bottomBright">?attr/colorBackground</item>
<item name="bottomMedium">?attr/colorBackground</item>
<item name="centerMedium">?attr/colorBackground</item>
- <item name="layout">@layout/alert_dialog_holo</item>
- <item name="listLayout">@layout/select_dialog_holo</item>
- <item name="progressLayout">@layout/progress_dialog_holo</item>
- <item name="horizontalProgressLayout">@layout/alert_dialog_progress_holo</item>
- <item name="listItemLayout">@layout/select_dialog_item_holo</item>
- <item name="multiChoiceItemLayout">@layout/select_dialog_multichoice_holo</item>
- <item name="singleChoiceItemLayout">@layout/select_dialog_singlechoice_holo</item>
+ <item name="layout">@layout/alert_dialog_quantum</item>
+ <item name="listLayout">@layout/select_dialog_quantum</item>
+ <item name="progressLayout">@layout/progress_dialog_quantum</item>
+ <item name="horizontalProgressLayout">@layout/alert_dialog_progress_quantum</item>
+ <item name="listItemLayout">@layout/select_dialog_item_quantum</item>
+ <item name="multiChoiceItemLayout">@layout/select_dialog_multichoice_quantum</item>
+ <item name="singleChoiceItemLayout">@layout/select_dialog_singlechoice_quantum</item>
</style>
- <style name="AlertDialog.Quantum.Light" />
+ <style name="AlertDialog.Quantum.Light"/>
<!-- Window title -->
<style name="WindowTitleBackground.Quantum">
@@ -1141,8 +1054,7 @@
<style name="WindowTitle.Quantum">
<item name="singleLine">true</item>
<item name="textAppearance">@style/TextAppearance.Quantum.WindowTitle</item>
- <item name="shadowColor">#BB000000</item>
- <item name="shadowRadius">2.75</item>
+ <item name="shadowRadius">0</item>
</style>
<style name="DialogWindowTitle.Quantum">
@@ -1152,60 +1064,7 @@
</style>
<style name="DialogWindowTitle.Quantum.Light">
- <item name="maxLines">1</item>
- <item name="scrollHorizontally">true</item>
<item name="textAppearance">@style/TextAppearance.Quantum.Light.DialogWindowTitle</item>
</style>
- <style name="Widget.Quantum.PreferenceFrameLayout">
- <item name="borderTop">0dip</item>
- <item name="borderBottom">@dimen/preference_fragment_padding_bottom</item>
- <item name="borderLeft">?attr/preferenceFragmentPaddingSide</item>
- <item name="borderRight">?attr/preferenceFragmentPaddingSide</item>
- </style>
-
- <style name="Widget.Quantum.MediaRouteButton">
- <item name="background">?attr/selectableItemBackground</item>
- <item name="externalRouteEnabledDrawable">@drawable/ic_media_route_holo_dark</item>
- <item name="minWidth">56dp</item>
- <item name="minHeight">48dp</item>
- <item name="focusable">true</item>
- <item name="contentDescription">@string/media_route_button_content_description</item>
- </style>
-
- <style name="Widget.Quantum.Light.MediaRouteButton" parent="Widget.Quantum.MediaRouteButton">
- <item name="externalRouteEnabledDrawable">@drawable/ic_media_route_holo_light</item>
- </style>
-
- <style name="TextAppearance.Quantum.TimePicker.TimeLabel" parent="TextAppearance.Quantum">
- <item name="textSize">@dimen/timepicker_time_label_size</item>
- <item name="textColor">@color/timepicker_default_text_color_quantum_dark</item>
- </style>
-
- <style name="TextAppearance.Quantum.TimePicker.AmPmLabel" parent="TextAppearance.Quantum">
- <item name="textSize">@dimen/timepicker_ampm_label_size</item>
- <item name="textAllCaps">true</item>
- <item name="textColor">@color/timepicker_default_text_color_quantum_dark</item>
- <item name="textStyle">bold</item>
- </style>
-
- <style name="TextAppearance.Quantum.Light.TimePicker.TimeLabel" parent="TextAppearance.Quantum.Light">
- <item name="textSize">@dimen/timepicker_time_label_size</item>
- <item name="textColor">@color/timepicker_default_text_color_quantum_light</item>
- </style>
-
- <style name="TextAppearance.Quantum.Light.TimePicker.AmPmLabel" parent="TextAppearance.Quantum.Light">
- <item name="textSize">@dimen/timepicker_ampm_label_size</item>
- <item name="textAllCaps">true</item>
- <item name="textColor">@color/timepicker_default_text_color_quantum_light</item>
- <item name="textStyle">bold</item>
- </style>
-
- <style name="Widget.Quantum.FastScroll" parent="Widget.FastScroll">
- <item name="thumbMinWidth">0dp</item>
- <item name="thumbMinHeight">0dp</item>
- </style>
-
- <style name="Widget.Quantum.Light.FastScroll" parent="Widget.Quantum.FastScroll"/>
-
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index efa873d..557dce24 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -346,6 +346,7 @@
<java-symbol type="dimen" name="notification_title_text_size" />
<java-symbol type="dimen" name="notification_subtext_size" />
<java-symbol type="dimen" name="immersive_mode_cling_width" />
+ <java-symbol type="dimen" name="notification_quantum_rounded_rect_radius" />
<java-symbol type="string" name="add_account_button_label" />
<java-symbol type="string" name="addToDictionary" />
@@ -1621,6 +1622,7 @@
<java-symbol type="string" name="enable_explore_by_touch_warning_message" />
<java-symbol type="bool" name="config_powerDecoupleAutoSuspendModeFromDisplay" />
<java-symbol type="bool" name="config_powerDecoupleInteractiveModeFromDisplay" />
+ <java-symbol type="string" name="config_customAdbPublicKeyActivity" />
<java-symbol type="layout" name="resolver_list" />
<java-symbol type="id" name="resolver_list" />
@@ -1637,6 +1639,8 @@
<java-symbol type="layout" name="notification_template_quantum_big_picture" />
<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="drawable" name="notification_icon_legacy_bg_inset" />
<!-- From SystemUI -->
<java-symbol type="anim" name="push_down_in" />
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 4a0158e..3c4e848 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -927,7 +927,7 @@
<item name="colorForeground">@android:color/bright_foreground_holo_dark</item>
<item name="colorForegroundInverse">@android:color/bright_foreground_inverse_holo_dark</item>
<item name="colorBackground">@android:color/background_holo_dark</item>
- <item name="colorBackgroundCacheHint">@android:drawable/background_cache_hint_selector_holo_dark</item>
+ <item name="colorBackgroundCacheHint">@android:color/background_cache_hint_selector_holo_dark</item>
<item name="disabledAlpha">0.5</item>
<item name="backgroundDimAmount">0.6</item>
@@ -1256,7 +1256,7 @@
<item name="colorForeground">@android:color/bright_foreground_holo_light</item>
<item name="colorForegroundInverse">@android:color/bright_foreground_inverse_holo_light</item>
<item name="colorBackground">@android:color/background_holo_light</item>
- <item name="colorBackgroundCacheHint">@android:drawable/background_cache_hint_selector_holo_light</item>
+ <item name="colorBackgroundCacheHint">@android:color/background_cache_hint_selector_holo_light</item>
<item name="disabledAlpha">0.5</item>
<item name="backgroundDimAmount">0.6</item>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 19556a1..0ce5094 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -32,24 +32,24 @@
-->
<resources>
- <!-- The default theme for apps that target API level 14 and higher.
+ <!-- The default theme for apps that target API level XX and higher.
<p>The DeviceDefault themes are aliases for a specific device’s native look and feel. The
DeviceDefault theme family and widget style family offer ways for you to target your app
to a device’s native theme with all device customizations intact.</p>
- <p>For example, when you set your app's {@code targetSdkVersion} to 14 or higher, this
+ <p>For example, when you set your app's {@code targetSdkVersion} to XX or higher, this
theme is applied to your application by default. As such, your app might appear with the
- {@link #Theme_Holo Holo} styles on one device, but with a different set of styles on
+ {@link #Theme_Quantum Quantum} styles on one device, but with a different set of styles on
another device. This is great if you want your app to fit with the device's native look and
feel. If, however, you prefer to keep your UI style the same across all devices, you should
- apply a specific theme such as {@link #Theme_Holo Holo} or one of your own design. For more
- information, read <a
- href="http://android-developers.blogspot.com/2012/01/holo-everywhere.html">Holo
+ apply a specific theme such as {@link #Theme_Quantum Quantum} or one of your own design.
+ For more information, read <a
+ href="http://android-developers.blogspot.com/20XX/XX/quantum-everywhere.html">Quantum
Everywhere</a>.</p>
<p>Styles used by the DeviceDefault theme are named using the convention
Type.DeviceDefault.Etc (for example, {@code Widget.DeviceDefault.Button} and
{@code TextAppearance.DeviceDefault.Widget.PopupMenu.Large}).</p>
-->
- <style name="Theme.DeviceDefault" parent="Theme.Holo" >
+ <style name="Theme.DeviceDefault" parent="Theme.Quantum" >
<!-- Text styles -->
<item name="textAppearance">@android:style/TextAppearance.DeviceDefault</item>
<item name="textAppearanceInverse">@android:style/TextAppearance.DeviceDefault.Inverse</item>
@@ -210,29 +210,29 @@
</style>
<!-- Variant of {@link #Theme_DeviceDefault} with no action bar -->
- <style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Holo.NoActionBar" >
+ <style name="Theme.DeviceDefault.NoActionBar" parent="Theme.Quantum.NoActionBar" >
</style>
<!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar. This theme
sets {@link android.R.attr#windowFullscreen} to true. -->
- <style name="Theme.DeviceDefault.NoActionBar.Fullscreen" parent="Theme.Holo.NoActionBar.Fullscreen" >
+ <style name="Theme.DeviceDefault.NoActionBar.Fullscreen" parent="Theme.Quantum.NoActionBar.Fullscreen" >
</style>
<!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar and
extending in to overscan region. This theme
sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
to true. -->
- <style name="Theme.DeviceDefault.NoActionBar.Overscan" parent="Theme.Holo.NoActionBar.Overscan" >
+ <style name="Theme.DeviceDefault.NoActionBar.Overscan" parent="Theme.Quantum.NoActionBar.Overscan" >
</style>
<!-- Variant of {@link #Theme_DeviceDefault} that has no title bar and translucent
system decor. This theme sets {@link android.R.attr#windowTranslucentStatus} and
{@link android.R.attr#windowTranslucentNavigation} to true. -->
- <style name="Theme.DeviceDefault.NoActionBar.TranslucentDecor" parent="Theme.Holo.NoActionBar.TranslucentDecor" >
+ <style name="Theme.DeviceDefault.NoActionBar.TranslucentDecor" parent="Theme.Quantum.NoActionBar.TranslucentDecor" >
</style>
<!-- Variant of {@link #Theme_DeviceDefault} with a light-colored style -->
- <style name="Theme.DeviceDefault.Light" parent="Theme.Holo.Light" >
+ <style name="Theme.DeviceDefault.Light" parent="Theme.Quantum.Light" >
<!-- Text styles -->
<item name="textAppearance">@android:style/TextAppearance.DeviceDefault.Light</item>
<item name="textAppearanceInverse">@android:style/TextAppearance.DeviceDefault.Light.Inverse</item>
@@ -387,29 +387,29 @@
<item name="mediaRouteButtonStyle">@android:style/Widget.DeviceDefault.Light.MediaRouteButton</item>
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar -->
- <style name="Theme.DeviceDefault.Light.NoActionBar" parent="Theme.Holo.Light.NoActionBar" >
+ <style name="Theme.DeviceDefault.Light.NoActionBar" parent="Theme.Quantum.Light.NoActionBar" >
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar.
This theme sets {@link android.R.attr#windowFullscreen} to true. -->
- <style name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen" parent="Theme.Holo.Light.NoActionBar.Fullscreen" >
+ <style name="Theme.DeviceDefault.Light.NoActionBar.Fullscreen" parent="Theme.Quantum.Light.NoActionBar.Fullscreen" >
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar
and extending in to overscan region. This theme
sets {@link android.R.attr#windowFullscreen} and {@link android.R.attr#windowOverscan}
to true. -->
<style name="Theme.DeviceDefault.Light.NoActionBar.Overscan"
- parent="Theme.Holo.Light.NoActionBar.Overscan" >
+ parent="Theme.Quantum.Light.NoActionBar.Overscan" >
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light} that has no title bar and translucent
system decor. This theme sets {@link android.R.attr#windowTranslucentStatus} and
{@link android.R.attr#windowTranslucentNavigation} to true. -->
<style name="Theme.DeviceDefault.Light.NoActionBar.TranslucentDecor"
- parent="Theme.Holo.Light.NoActionBar.TranslucentDecor" >
+ parent="Theme.Quantum.Light.NoActionBar.TranslucentDecor" >
</style>
<!-- DeviceDefault theme for dialog windows and activities. This changes the window to be
floating (not fill the entire screen), and puts a frame around its contents. You can set this
theme on an activity if you would like to make an activity that looks like a Dialog. -->
- <style name="Theme.DeviceDefault.Dialog" parent="Theme.Holo.Dialog" >
+ <style name="Theme.DeviceDefault.Dialog" parent="Theme.Quantum.Dialog" >
<item name="android:windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault</item>
<item name="android:windowAnimationStyle">@android:style/Animation.DeviceDefault.Dialog</item>
@@ -421,16 +421,16 @@
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Dialog} that has a nice minimum width for a
regular dialog. -->
- <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Holo.Dialog.MinWidth" >
+ <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Quantum.Dialog.MinWidth" >
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Dialog} without an action bar -->
- <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Holo.Dialog.NoActionBar" >
+ <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Quantum.Dialog.NoActionBar" >
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Dialog_NoActionBar} that has a nice minimum width
for a regular dialog. -->
- <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Holo.Dialog.NoActionBar.MinWidth" >
+ <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Quantum.Dialog.NoActionBar.MinWidth" >
</style>
@@ -453,7 +453,7 @@
<!-- DeviceDefault light theme for dialog windows and activities. This changes the window to be
floating (not fill the entire screen), and puts a frame around its contents. You can set this
theme on an activity if you would like to make an activity that looks like a Dialog.-->
- <style name="Theme.DeviceDefault.Light.Dialog" parent="Theme.Holo.Light.Dialog" >
+ <style name="Theme.DeviceDefault.Light.Dialog" parent="Theme.Quantum.Light.Dialog" >
<item name="android:windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault.Light</item>
<item name="android:windowAnimationStyle">@android:style/Animation.DeviceDefault.Dialog</item>
@@ -465,16 +465,16 @@
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} that has a nice minimum width for a
regular dialog. -->
- <style name="Theme.DeviceDefault.Light.Dialog.MinWidth" parent="Theme.Holo.Light.Dialog.MinWidth" >
+ <style name="Theme.DeviceDefault.Light.Dialog.MinWidth" parent="Theme.Quantum.Light.Dialog.MinWidth" >
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} without an action bar -->
- <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar" parent="Theme.Holo.Light.Dialog.NoActionBar" >
+ <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar" parent="Theme.Quantum.Light.Dialog.NoActionBar" >
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog_NoActionBar} that has a nice minimum
width for a regular dialog. -->
- <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth" parent="Theme.Holo.Light.Dialog.NoActionBar.MinWidth" >
+ <style name="Theme.DeviceDefault.Light.Dialog.NoActionBar.MinWidth" parent="Theme.Quantum.Light.Dialog.NoActionBar.MinWidth" >
</style>
@@ -496,65 +496,65 @@
<!-- DeviceDefault theme for a window that will be displayed either full-screen on smaller
screens (small, normal) or as a dialog on larger screens (large, xlarge). -->
- <style name="Theme.DeviceDefault.DialogWhenLarge" parent="Theme.Holo.DialogWhenLarge" >
+ <style name="Theme.DeviceDefault.DialogWhenLarge" parent="Theme.Quantum.DialogWhenLarge" >
</style>
<!-- DeviceDefault theme for a window without an action bar that will be displayed either
full-screen on smaller screens (small, normal) or as a dialog on larger screens (large,
xlarge). -->
- <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="Theme.Holo.DialogWhenLarge.NoActionBar" >
+ <style name="Theme.DeviceDefault.DialogWhenLarge.NoActionBar" parent="Theme.Quantum.DialogWhenLarge.NoActionBar" >
</style>
<!-- DeviceDefault light theme for a window that will be displayed either full-screen on smaller
screens (small, normal) or as a dialog on larger screens (large, xlarge). -->
- <style name="Theme.DeviceDefault.Light.DialogWhenLarge" parent="Theme.Holo.Light.DialogWhenLarge" >
+ <style name="Theme.DeviceDefault.Light.DialogWhenLarge" parent="Theme.Quantum.Light.DialogWhenLarge" >
</style>
<!-- DeviceDefault light theme for a window without an action bar that will be displayed either
full-screen on smaller screens (small, normal) or as a dialog on larger screens (large,
xlarge). -->
- <style name="Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar" parent="Theme.Holo.Light.DialogWhenLarge.NoActionBar" >
+ <style name="Theme.DeviceDefault.Light.DialogWhenLarge.NoActionBar" parent="Theme.Quantum.Light.DialogWhenLarge.NoActionBar" >
</style>
<!-- DeviceDefault theme for a presentation window on a secondary display. -->
- <style name="Theme.DeviceDefault.Dialog.Presentation" parent="Theme.Holo.Dialog.Presentation">
+ <style name="Theme.DeviceDefault.Dialog.Presentation" parent="Theme.Quantum.Dialog.Presentation">
</style>
<!-- DeviceDefault light theme for a presentation window on a secondary display. -->
- <style name="Theme.DeviceDefault.Light.Dialog.Presentation" parent="Theme.Holo.Light.Dialog.Presentation">
+ <style name="Theme.DeviceDefault.Light.Dialog.Presentation" parent="Theme.Quantum.Light.Dialog.Presentation">
</style>
<!-- DeviceDefault theme for panel windows. This removes all extraneous window
decorations, so you basically have an empty rectangle in which to place your content. It makes
the window floating, with a transparent background, and turns off dimming behind the window. -->
- <style name="Theme.DeviceDefault.Panel" parent="Theme.Holo.Panel" >
+ <style name="Theme.DeviceDefault.Panel" parent="Theme.Quantum.Panel" >
</style>
<!-- DeviceDefault light theme for panel windows. This removes all extraneous window
decorations, so you basically have an empty rectangle in which to place your content. It makes
the window floating, with a transparent background, and turns off dimming behind the window. -->
- <style name="Theme.DeviceDefault.Light.Panel" parent="Theme.Holo.Light.Panel" >
+ <style name="Theme.DeviceDefault.Light.Panel" parent="Theme.Quantum.Light.Panel" >
</style>
<!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
behind them. -->
- <style name="Theme.DeviceDefault.Wallpaper" parent="Theme.Holo.Wallpaper" >
+ <style name="Theme.DeviceDefault.Wallpaper" parent="Theme.Quantum.Wallpaper" >
</style>
<!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
behind them and without an action bar. -->
- <style name="Theme.DeviceDefault.Wallpaper.NoTitleBar" parent="Theme.Holo.Wallpaper.NoTitleBar" >
+ <style name="Theme.DeviceDefault.Wallpaper.NoTitleBar" parent="Theme.Quantum.Wallpaper.NoTitleBar" >
</style>
<!-- DeviceDefault style for input methods, which is used by the
{@link android.inputmethodservice.InputMethodService} class.-->
- <style name="Theme.DeviceDefault.InputMethod" parent="Theme.Holo.InputMethod" >
+ <style name="Theme.DeviceDefault.InputMethod" parent="Theme.Quantum.InputMethod" >
</style>
<!-- Variant of the DeviceDefault (light) theme that has a solid (opaque) action bar with an
inverse color profile. -->
- <style name="Theme.DeviceDefault.Light.DarkActionBar" parent="Theme.Holo.Light.DarkActionBar" >
+ <style name="Theme.DeviceDefault.Light.DarkActionBar" parent="Theme.Quantum.Light.DarkActionBar" >
<item name="android:actionBarStyle">@android:style/Widget.DeviceDefault.Light.ActionBar.Solid.Inverse</item>
<item name="actionDropDownStyle">@android:style/Widget.DeviceDefault.Spinner.DropDown.ActionBar</item>
@@ -569,20 +569,20 @@
</style>
- <style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Holo.Dialog.Alert">
+ <style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Quantum.Dialog.Alert">
<item name="windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault</item>
</style>
- <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Holo.Light.Dialog.Alert">
+ <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Quantum.Light.Dialog.Alert">
<item name="windowTitleStyle">@android:style/DialogWindowTitle.DeviceDefault.Light</item>
</style>
- <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Holo.SearchBar">
+ <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Quantum.SearchBar">
</style>
- <style name="Theme.DeviceDefault.Light.SearchBar" parent="Theme.Holo.Light.SearchBar">
+ <style name="Theme.DeviceDefault.Light.SearchBar" parent="Theme.Quantum.Light.SearchBar">
</style>
- <style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Holo.Dialog.NoFrame">
+ <style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Quantum.Dialog.NoFrame">
</style>
</resources>
diff --git a/core/res/res/values/themes_micro.xml b/core/res/res/values/themes_micro.xml
index 7c0b7bc..f51b8df 100644
--- a/core/res/res/values/themes_micro.xml
+++ b/core/res/res/values/themes_micro.xml
@@ -23,7 +23,7 @@
<item name="windowSwipeToDismiss">true</item>
</style>
- <style name="Theme.Micro.NoActionBar" parent="Theme.Holo.NoActionBar">
+ <style name="Theme.Micro.Light" parent="Theme.Holo.Light.NoActionBar">
<item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
<item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
<item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
@@ -31,28 +31,4 @@
<item name="windowIsTranslucent">true</item>
<item name="windowSwipeToDismiss">true</item>
</style>
- <style name="Theme.Micro.Light" parent="Theme.Holo.Light">
- <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
- <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
- <item name="windowIsFloating">false</item>
- <item name="windowIsTranslucent">true</item>
- <item name="windowSwipeToDismiss">true</item>
- </style>
- <style name="Theme.Micro.Light.NoActionBar" parent="Theme.Holo.Light.NoActionBar">
- <item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
- <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
- <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
- <item name="windowIsFloating">false</item>
- <item name="windowIsTranslucent">true</item>
- <item name="windowSwipeToDismiss">true</item>
- </style>
- <style name="Theme.Micro.Light.DarkActionBar" parent="Theme.Holo.Light.DarkActionBar">
- <item name="textViewStyle">@android:style/Widget.Micro.TextView</item>
- <item name="numberPickerStyle">@android:style/Widget.Micro.NumberPicker</item>
- <item name="windowAnimationStyle">@android:style/Animation.SwipeDismiss</item>
- <item name="windowIsFloating">false</item>
- <item name="windowIsTranslucent">true</item>
- <item name="windowSwipeToDismiss">true</item>
- </style>
-
</resources>
diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml
index d2eee28..50f1ca6 100644
--- a/core/res/res/values/themes_quantum.xml
+++ b/core/res/res/values/themes_quantum.xml
@@ -45,7 +45,7 @@
<item name="colorForeground">@color/bright_foreground_quantum_dark</item>
<item name="colorForegroundInverse">@color/bright_foreground_quantum_light</item>
<item name="colorBackground">@color/background_quantum_dark</item>
- <item name="colorBackgroundCacheHint">@drawable/background_cache_hint_selector_quantum_dark</item>
+ <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_quantum_dark</item>
<item name="disabledAlpha">0.5</item>
<item name="backgroundDimAmount">0.6</item>
@@ -81,7 +81,7 @@
<item name="textAppearanceButton">@style/TextAppearance.Quantum.Widget.Button</item>
<item name="editTextColor">?attr/textColorPrimary</item>
- <item name="editTextBackground">@drawable/edit_text_quantum_dark</item>
+ <item name="editTextBackground">@drawable/edit_text_quantum</item>
<item name="candidatesTextStyleSpans">@string/candidates_style</item>
@@ -100,9 +100,9 @@
<item name="switchStyle">@style/Widget.Quantum.CompoundButton.Switch</item>
<item name="mediaRouteButtonStyle">@style/Widget.Quantum.MediaRouteButton</item>
- <item name="selectableItemBackground">@drawable/item_background_quantum_dark</item>
+ <item name="selectableItemBackground">@drawable/item_background_quantum</item>
<item name="borderlessButtonStyle">@style/Widget.Quantum.Button.Borderless</item>
- <item name="homeAsUpIndicator">@drawable/ic_ab_back_quantum_dark</item>
+ <item name="homeAsUpIndicator">@drawable/ic_ab_back_quantum</item>
<!-- List attributes -->
<item name="listPreferredItemHeight">64dip</item>
@@ -117,17 +117,17 @@
<!-- @hide -->
<item name="searchResultListItemHeight">58dip</item>
- <item name="listDivider">@drawable/list_divider_quantum_dark</item>
+ <item name="listDivider">@drawable/list_divider_quantum</item>
<item name="listSeparatorTextViewStyle">@style/Widget.Quantum.TextView.ListSeparator</item>
- <item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum_dark</item>
- <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum_dark</item>
+ <item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum</item>
+ <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum</item>
<item name="listChoiceBackgroundIndicator">@drawable/list_selector_holo_dark</item>
- <item name="activatedBackgroundIndicator">@drawable/activated_background_quantum_dark</item>
+ <item name="activatedBackgroundIndicator">@drawable/activated_background_quantum</item>
- <item name="listDividerAlertDialog">@drawable/list_divider_quantum_dark</item>
+ <item name="listDividerAlertDialog">@drawable/list_divider_quantum</item>
<item name="expandableListPreferredItemPaddingLeft">40dip</item>
<item name="expandableListPreferredChildPaddingLeft">?attr/expandableListPreferredItemPaddingLeft</item>
@@ -136,8 +136,8 @@
<item name="expandableListPreferredItemIndicatorRight">0dip</item>
<item name="expandableListPreferredChildIndicatorLeft">?attr/expandableListPreferredItemIndicatorLeft</item>
<item name="expandableListPreferredChildIndicatorRight">?attr/expandableListPreferredItemIndicatorRight</item>
- <item name="findOnPageNextDrawable">@drawable/ic_find_next_quantum_dark</item>
- <item name="findOnPagePreviousDrawable">@drawable/ic_find_previous_quantum_dark</item>
+ <item name="findOnPageNextDrawable">@drawable/ic_find_next_quantum</item>
+ <item name="findOnPagePreviousDrawable">@drawable/ic_find_previous_quantum</item>
<!-- Gallery attributes -->
<item name="galleryItemBackground">@drawable/gallery_item_background</item>
@@ -154,7 +154,7 @@
<item name="windowTitleStyle">@style/WindowTitle.Quantum</item>
<item name="windowTitleSize">25dip</item>
<item name="windowTitleBackgroundStyle">@style/WindowTitleBackground.Quantum</item>
- <item name="windowContentTransitions">true</item>
+ <item name="windowContentTransitions">false</item>
<item name="windowAnimationStyle">@style/Animation.Quantum.Activity</item>
<item name="windowSoftInputMode">stateUnspecified|adjustUnspecified</item>
<item name="windowActionBar">true</item>
@@ -162,15 +162,15 @@
<!-- Dialog attributes -->
<item name="dialogTheme">@style/Theme.Quantum.Dialog</item>
- <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_holo</item>
- <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_holo</item>
- <item name="dialogTitleDecorLayout">@layout/dialog_title_holo</item>
+ <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_quantum</item>
+ <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_quantum</item>
+ <item name="dialogTitleDecorLayout">@layout/dialog_title_quantum</item>
<!-- AlertDialog attributes -->
<item name="alertDialogTheme">@style/Theme.Quantum.Dialog.Alert</item>
<item name="alertDialogStyle">@style/AlertDialog.Quantum</item>
<item name="alertDialogCenterButtons">false</item>
- <item name="alertDialogIcon">@drawable/ic_dialog_alert_quantum_dark</item>
+ <item name="alertDialogIcon">@drawable/ic_dialog_alert_quantum</item>
<!-- Presentation attributes -->
<item name="presentationTheme">@style/Theme.Quantum.Dialog.Presentation</item>
@@ -194,8 +194,8 @@
<item name="scrollbarFadeDuration">250</item>
<item name="scrollbarDefaultDelayBeforeFade">300</item>
<item name="scrollbarSize">10dip</item>
- <item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_quantum_dark</item>
- <item name="scrollbarThumbVertical">@drawable/scrollbar_handle_quantum_dark</item>
+ <item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_quantum</item>
+ <item name="scrollbarThumbVertical">@drawable/scrollbar_handle_quantum</item>
<item name="scrollbarTrackHorizontal">@null</item>
<item name="scrollbarTrackVertical">@null</item>
@@ -205,7 +205,7 @@
<item name="textSelectHandle">@drawable/text_select_handle_middle</item>
<item name="textSelectHandleWindowStyle">@style/Widget.Quantum.TextSelectHandle</item>
<item name="textSuggestionsWindowStyle">@style/Widget.Quantum.TextSuggestionsPopupWindow</item>
- <item name="textCursorDrawable">@drawable/text_cursor_quantum_dark</item>
+ <item name="textCursorDrawable">@drawable/text_cursor_quantum</item>
<!-- Widget styles -->
<item name="absListViewStyle">@style/Widget.Quantum.AbsListView</item>
@@ -290,7 +290,7 @@
<item name="actionOverflowButtonStyle">@style/Widget.Quantum.ActionButton.Overflow</item>
<item name="actionModeBackground">@color/theme_color_700</item>
<item name="actionModeSplitBackground">@color/theme_color_700</item>
- <item name="actionModeCloseDrawable">@drawable/ic_cab_done_quantum_dark</item>
+ <item name="actionModeCloseDrawable">@drawable/ic_cab_done_quantum</item>
<item name="actionBarTabStyle">@style/Widget.Quantum.ActionBar.TabView</item>
<item name="actionBarTabBarStyle">@style/Widget.Quantum.ActionBar.TabBar</item>
<item name="actionBarTabTextStyle">@style/Widget.Quantum.ActionBar.TabText</item>
@@ -300,21 +300,21 @@
<item name="actionBarSize">@dimen/action_bar_default_height</item>
<item name="actionModePopupWindowStyle">@style/Widget.Quantum.PopupWindow.ActionMode</item>
<item name="actionBarWidgetTheme">@null</item>
- <item name="actionBarItemBackground">@drawable/item_background_borderless_quantum_dark</item>
+ <item name="actionBarItemBackground">@drawable/item_background_quantum</item>
- <item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum_dark</item>
- <item name="actionModeCopyDrawable">@drawable/ic_menu_copy_quantum_dark</item>
- <item name="actionModePasteDrawable">@drawable/ic_menu_paste_quantum_dark</item>
- <item name="actionModeSelectAllDrawable">@drawable/ic_menu_selectall_quantum_dark</item>
- <item name="actionModeShareDrawable">@drawable/ic_menu_share_quantum_dark</item>
- <item name="actionModeFindDrawable">@drawable/ic_menu_find_quantum_dark</item>
- <item name="actionModeWebSearchDrawable">@drawable/ic_menu_search_quantum_dark</item>
+ <item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum</item>
+ <item name="actionModeCopyDrawable">@drawable/ic_menu_copy_quantum</item>
+ <item name="actionModePasteDrawable">@drawable/ic_menu_paste_quantum</item>
+ <item name="actionModeSelectAllDrawable">@drawable/ic_menu_selectall_quantum</item>
+ <item name="actionModeShareDrawable">@drawable/ic_menu_share_quantum</item>
+ <item name="actionModeFindDrawable">@drawable/ic_menu_find_quantum</item>
+ <item name="actionModeWebSearchDrawable">@drawable/ic_menu_search_quantum</item>
<item name="dividerVertical">?attr/listDivider</item>
<item name="dividerHorizontal">?attr/listDivider</item>
- <item name="buttonBarStyle">@style/Quantum.ButtonBar</item>
+ <item name="buttonBarStyle">@style/Widget.Quantum.ButtonBar</item>
<item name="buttonBarButtonStyle">?attr/borderlessButtonStyle</item>
- <item name="segmentedButtonStyle">@style/Quantum.SegmentedButton</item>
+ <item name="segmentedButtonStyle">@style/Widget.Quantum.SegmentedButton</item>
<!-- SearchView attributes -->
<item name="searchDropdownBackground">@drawable/search_dropdown_dark</item>
@@ -349,11 +349,20 @@
<item name="datePickerStyle">@style/Widget.Quantum.DatePicker</item>
<!-- TODO: This belongs in a FastScroll style -->
- <item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_quantum_light</item>
+ <item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_quantum</item>
<item name="fastScrollPreviewBackgroundLeft">@drawable/fastscroll_label_left_holo_dark</item>
<item name="fastScrollPreviewBackgroundRight">@drawable/fastscroll_label_right_holo_dark</item>
- <item name="fastScrollTrackDrawable">@drawable/fastscroll_track_quantum_dark</item>
+ <item name="fastScrollTrackDrawable">@drawable/fastscroll_track_quantum</item>
<item name="fastScrollOverlayPosition">atThumb</item>
+
+ <!-- Color palette -->
+ <item name="colorControlNormal">@color/control_normal_foreground_quantum_dark</item>
+ <item name="colorControlActivated">@color/control_activated_foreground_quantum_dark</item>
+ <item name="colorButtonNormal">@color/btn_default_normal_quantum_dark</item>
+ <item name="colorButtonPressed">@color/btn_default_pressed_quantum_dark</item>
+ <!-- TODO: Remove these attrs and move into button style. -->
+ <item name="colorButtonNormalColored">@color/theme_color_500</item>
+ <item name="colorButtonPressedColored">@color/theme_color_300</item>
</style>
<!-- Quantum Paper theme (light version). -->
@@ -361,7 +370,7 @@
<item name="colorForeground">@color/bright_foreground_quantum_light</item>
<item name="colorForegroundInverse">@color/bright_foreground_quantum_dark</item>
<item name="colorBackground">@color/background_quantum_light</item>
- <item name="colorBackgroundCacheHint">@drawable/background_cache_hint_selector_quantum_light</item>
+ <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_quantum_light</item>
<item name="disabledAlpha">0.5</item>
<item name="backgroundDimAmount">0.6</item>
@@ -398,7 +407,7 @@
<item name="textAppearanceButton">@style/TextAppearance.Quantum.Light.Widget.Button</item>
<item name="editTextColor">?attr/textColorPrimary</item>
- <item name="editTextBackground">@drawable/edit_text_quantum_light</item>
+ <item name="editTextBackground">@drawable/edit_text_quantum</item>
<item name="candidatesTextStyleSpans">@string/candidates_style</item>
@@ -418,9 +427,9 @@
<item name="switchStyle">@style/Widget.Quantum.Light.CompoundButton.Switch</item>
<item name="mediaRouteButtonStyle">@style/Widget.Quantum.Light.MediaRouteButton</item>
- <item name="selectableItemBackground">@drawable/item_background_quantum_light</item>
+ <item name="selectableItemBackground">@drawable/item_background_quantum</item>
<item name="borderlessButtonStyle">@style/Widget.Quantum.Light.Button.Borderless</item>
- <item name="homeAsUpIndicator">@drawable/ic_ab_back_quantum_light</item>
+ <item name="homeAsUpIndicator">@drawable/ic_ab_back_quantum</item>
<!-- List attributes -->
<item name="listPreferredItemHeight">64dip</item>
@@ -435,15 +444,15 @@
<!-- @hide -->
<item name="searchResultListItemHeight">58dip</item>
- <item name="listDivider">@drawable/list_divider_quantum_light</item>
+ <item name="listDivider">@drawable/list_divider_quantum</item>
<item name="listSeparatorTextViewStyle">@style/Widget.Quantum.Light.TextView.ListSeparator</item>
- <item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum_light</item>
- <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum_light</item>
+ <item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum</item>
+ <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum</item>
<item name="listChoiceBackgroundIndicator">@drawable/list_selector_holo_light</item>
- <item name="activatedBackgroundIndicator">@drawable/activated_background_quantum_light</item>
+ <item name="activatedBackgroundIndicator">@drawable/activated_background_quantum</item>
<item name="expandableListPreferredItemPaddingLeft">40dip</item>
<item name="expandableListPreferredChildPaddingLeft">?attr/expandableListPreferredItemPaddingLeft</item>
@@ -453,9 +462,9 @@
<item name="expandableListPreferredChildIndicatorLeft">?attr/expandableListPreferredItemIndicatorLeft</item>
<item name="expandableListPreferredChildIndicatorRight">?attr/expandableListPreferredItemIndicatorRight</item>
- <item name="listDividerAlertDialog">@drawable/list_divider_quantum_light</item>
- <item name="findOnPageNextDrawable">@drawable/ic_find_next_quantum_light</item>
- <item name="findOnPagePreviousDrawable">@drawable/ic_find_previous_quantum_light</item>
+ <item name="listDividerAlertDialog">@drawable/list_divider_quantum</item>
+ <item name="findOnPageNextDrawable">@drawable/ic_find_next_quantum</item>
+ <item name="findOnPagePreviousDrawable">@drawable/ic_find_previous_quantum</item>
<!-- Gallery attributes -->
<item name="galleryItemBackground">@drawable/gallery_item_background</item>
@@ -467,7 +476,7 @@
<item name="windowFullscreen">false</item>
<item name="windowOverscan">false</item>
<item name="windowIsFloating">false</item>
- <item name="windowContentOverlay">@drawable/ab_solid_shadow_qntm</item>
+ <item name="windowContentOverlay">@drawable/ab_solid_shadow_quantum</item>
<item name="windowShowWallpaper">false</item>
<item name="windowTitleStyle">@style/WindowTitle.Quantum</item>
<item name="windowTitleSize">25dip</item>
@@ -479,15 +488,15 @@
<!-- Dialog attributes -->
<item name="dialogTheme">@style/Theme.Quantum.Light.Dialog</item>
- <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_holo</item>
- <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_holo</item>
- <item name="dialogTitleDecorLayout">@layout/dialog_title_holo</item>
+ <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_quantum</item>
+ <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_quantum</item>
+ <item name="dialogTitleDecorLayout">@layout/dialog_title_quantum</item>
<!-- AlertDialog attributes -->
<item name="alertDialogTheme">@style/Theme.Quantum.Light.Dialog.Alert</item>
<item name="alertDialogStyle">@style/AlertDialog.Quantum.Light</item>
<item name="alertDialogCenterButtons">false</item>
- <item name="alertDialogIcon">@drawable/ic_dialog_alert_quantum_light</item>
+ <item name="alertDialogIcon">@drawable/ic_dialog_alert_quantum</item>
<!-- Presentation attributes -->
<item name="presentationTheme">@style/Theme.Quantum.Light.Dialog.Presentation</item>
@@ -511,8 +520,8 @@
<item name="scrollbarFadeDuration">250</item>
<item name="scrollbarDefaultDelayBeforeFade">300</item>
<item name="scrollbarSize">10dip</item>
- <item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_quantum_light</item>
- <item name="scrollbarThumbVertical">@drawable/scrollbar_handle_quantum_light</item>
+ <item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_quantum</item>
+ <item name="scrollbarThumbVertical">@drawable/scrollbar_handle_quantum</item>
<item name="scrollbarTrackHorizontal">@null</item>
<item name="scrollbarTrackVertical">@null</item>
@@ -522,7 +531,7 @@
<item name="textSelectHandle">@drawable/text_select_handle_middle</item>
<item name="textSelectHandleWindowStyle">@style/Widget.Quantum.TextSelectHandle</item>
<item name="textSuggestionsWindowStyle">@style/Widget.Quantum.Light.TextSuggestionsPopupWindow</item>
- <item name="textCursorDrawable">@drawable/text_cursor_quantum_light</item>
+ <item name="textCursorDrawable">@drawable/text_cursor_quantum</item>
<!-- Widget styles -->
<item name="absListViewStyle">@style/Widget.Quantum.Light.AbsListView</item>
@@ -610,7 +619,7 @@
<item name="actionOverflowButtonStyle">@style/Widget.Quantum.Light.ActionButton.Overflow</item>
<item name="actionModeBackground">@drawable/cab_background_top_holo_light</item>
<item name="actionModeSplitBackground">@drawable/cab_background_bottom_holo_light</item>
- <item name="actionModeCloseDrawable">@drawable/ic_cab_done_quantum_light</item>
+ <item name="actionModeCloseDrawable">@drawable/ic_cab_done_quantum</item>
<item name="actionBarTabStyle">@style/Widget.Quantum.Light.ActionBar.TabView</item>
<item name="actionBarTabBarStyle">@style/Widget.Quantum.Light.ActionBar.TabBar</item>
<item name="actionBarTabTextStyle">@style/Widget.Quantum.Light.ActionBar.TabText</item>
@@ -620,21 +629,21 @@
<item name="actionBarSize">@dimen/action_bar_default_height</item>
<item name="actionModePopupWindowStyle">@style/Widget.Quantum.Light.PopupWindow.ActionMode</item>
<item name="actionBarWidgetTheme">@null</item>
- <item name="actionBarItemBackground">@drawable/item_background_borderless_quantum_light</item>
+ <item name="actionBarItemBackground">@drawable/item_background_quantum</item>
- <item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum_light</item>
- <item name="actionModeCopyDrawable">@drawable/ic_menu_copy_quantum_light</item>
- <item name="actionModePasteDrawable">@drawable/ic_menu_paste_quantum_light</item>
- <item name="actionModeSelectAllDrawable">@drawable/ic_menu_selectall_quantum_light</item>
- <item name="actionModeShareDrawable">@drawable/ic_menu_share_quantum_light</item>
- <item name="actionModeFindDrawable">@drawable/ic_menu_find_quantum_light</item>
- <item name="actionModeWebSearchDrawable">@drawable/ic_menu_search_quantum_light</item>
+ <item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum</item>
+ <item name="actionModeCopyDrawable">@drawable/ic_menu_copy_quantum</item>
+ <item name="actionModePasteDrawable">@drawable/ic_menu_paste_quantum</item>
+ <item name="actionModeSelectAllDrawable">@drawable/ic_menu_selectall_quantum</item>
+ <item name="actionModeShareDrawable">@drawable/ic_menu_share_quantum</item>
+ <item name="actionModeFindDrawable">@drawable/ic_menu_find_quantum</item>
+ <item name="actionModeWebSearchDrawable">@drawable/ic_menu_search_quantum</item>
<item name="dividerVertical">?attr/listDivider</item>
<item name="dividerHorizontal">?attr/listDivider</item>
- <item name="buttonBarStyle">@style/Quantum.Light.ButtonBar</item>
+ <item name="buttonBarStyle">@style/Widget.Quantum.Light.ButtonBar</item>
<item name="buttonBarButtonStyle">?attr/borderlessButtonStyle</item>
- <item name="segmentedButtonStyle">@style/Quantum.Light.SegmentedButton</item>
+ <item name="segmentedButtonStyle">@style/Widget.Quantum.Light.SegmentedButton</item>
<!-- SearchView attributes -->
<item name="searchDropdownBackground">@drawable/search_dropdown_light</item>
@@ -665,18 +674,27 @@
<!-- DatePicker style -->
<item name="datePickerStyle">@style/Widget.Quantum.Light.DatePicker</item>
- <item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_quantum_light</item>
+ <item name="fastScrollThumbDrawable">@drawable/fastscroll_thumb_quantum</item>
<item name="fastScrollPreviewBackgroundLeft">@drawable/fastscroll_label_left_holo_light</item>
<item name="fastScrollPreviewBackgroundRight">@drawable/fastscroll_label_right_holo_light</item>
- <item name="fastScrollTrackDrawable">@drawable/fastscroll_track_quantum_light</item>
+ <item name="fastScrollTrackDrawable">@drawable/fastscroll_track_quantum</item>
<item name="fastScrollOverlayPosition">atThumb</item>
+
+ <!-- Color palette -->
+ <item name="colorControlNormal">@color/control_normal_foreground_quantum_light</item>
+ <item name="colorControlActivated">@color/control_activated_foreground_quantum_light</item>
+ <item name="colorButtonNormal">@color/btn_default_normal_quantum_light</item>
+ <item name="colorButtonPressed">@color/btn_default_pressed_quantum_light</item>
+ <!-- TODO: Remove these attrs and move into button style. -->
+ <item name="colorButtonNormalColored">@color/theme_color_500</item>
+ <item name="colorButtonPressedColored">@color/theme_color_700</item>
</style>
<!-- Variant of the quantum (light) theme that has a solid (opaque) action bar
with an inverse color profile. The dark action bar sharply stands out against
the light content. -->
<style name="Theme.Quantum.Light.DarkActionBar">
- <item name="actionBarTheme">@style/Theme.Quantum</item>
+ <item name="actionBarWidgetTheme">@style/Theme.Quantum</item>
</style>
<!-- Variant of the quantum (dark) theme with no action bar. -->
@@ -841,7 +859,7 @@
<item name="colorBackgroundCacheHint">@null</item>
- <item name="buttonBarStyle">@style/Quantum.ButtonBar.AlertDialog</item>
+ <item name="buttonBarStyle">@style/Widget.Quantum.ButtonBar.AlertDialog</item>
<item name="borderlessButtonStyle">@style/Widget.Quantum.Button.Borderless.Small</item>
<item name="textAppearance">@style/TextAppearance.Quantum</item>
@@ -963,7 +981,7 @@
<item name="colorBackgroundCacheHint">@null</item>
- <item name="buttonBarStyle">@style/Quantum.Light.ButtonBar.AlertDialog</item>
+ <item name="buttonBarStyle">@style/Widget.Quantum.Light.ButtonBar.AlertDialog</item>
<item name="borderlessButtonStyle">@style/Widget.Quantum.Light.Button.Borderless.Small</item>
<item name="textAppearance">@style/TextAppearance.Quantum.Light</item>
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 04f8009..e77564f 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -21,6 +21,7 @@
import com.android.frameworks.coretests.R;
import com.android.internal.content.PackageHelper;
+import android.app.PackageInstallObserver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -31,6 +32,7 @@
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Environment;
import android.os.FileUtils;
import android.os.IBinder;
@@ -117,12 +119,12 @@
super.tearDown();
}
- private class PackageInstallObserver extends IPackageInstallObserver.Stub {
+ private class TestInstallObserver extends PackageInstallObserver {
public int returnCode;
private boolean doneFlag = false;
- public void packageInstalled(String packageName, int returnCode) {
+ public void packageInstalled(String packageName, Bundle extras, int returnCode) {
synchronized (this) {
this.returnCode = returnCode;
doneFlag = true;
@@ -203,7 +205,7 @@
public void invokeInstallPackage(Uri packageURI, int flags, GenericReceiver receiver,
boolean shouldSucceed) {
- PackageInstallObserver observer = new PackageInstallObserver();
+ TestInstallObserver observer = new TestInstallObserver();
mContext.registerReceiver(receiver, receiver.filter);
try {
// Wait on observer
@@ -261,7 +263,7 @@
}
public void invokeInstallPackageFail(Uri packageURI, int flags, int expectedResult) {
- PackageInstallObserver observer = new PackageInstallObserver();
+ TestInstallObserver observer = new TestInstallObserver();
try {
// Wait on observer
synchronized (observer) {
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 0d9a386..97c1b33 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -133,6 +133,8 @@
RobotoCondensed-Bold.ttf \
RobotoCondensed-Italic.ttf \
RobotoCondensed-BoldItalic.ttf \
+ RobotoCondensed-Light.ttf \
+ RobotoCondensed-LightItalic.ttf \
DroidNaskh-Regular.ttf \
DroidNaskhUI-Regular.ttf \
DroidSansHebrew-Regular.ttf \
diff --git a/data/fonts/RobotoCondensed-Light.ttf b/data/fonts/RobotoCondensed-Light.ttf
new file mode 100644
index 0000000..41d212a
--- /dev/null
+++ b/data/fonts/RobotoCondensed-Light.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-LightItalic.ttf b/data/fonts/RobotoCondensed-LightItalic.ttf
new file mode 100755
index 0000000..dd54971
--- /dev/null
+++ b/data/fonts/RobotoCondensed-LightItalic.ttf
Binary files differ
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index 05cca13..293ecc8 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -32,6 +32,8 @@
RobotoCondensed-Bold.ttf \
RobotoCondensed-Italic.ttf \
RobotoCondensed-BoldItalic.ttf \
+ RobotoCondensed-Light.ttf \
+ RobotoCondensed-LightItalic.ttf \
DroidNaskh-Regular.ttf \
DroidNaskhUI-Regular.ttf \
DroidSansHebrew-Regular.ttf \
diff --git a/data/fonts/system_fonts.xml b/data/fonts/system_fonts.xml
index 549f061b..a8d23ee 100644
--- a/data/fonts/system_fonts.xml
+++ b/data/fonts/system_fonts.xml
@@ -65,6 +65,17 @@
<file>RobotoCondensed-BoldItalic.ttf</file>
</fileset>
</family>
+
+ <family>
+ <nameset>
+ <name>sans-serif-condensed-light</name>
+ </nameset>
+ <fileset>
+ <file>RobotoCondensed-Light.ttf</file>
+ <file>RobotoCondensed-LightItalic.ttf</file>
+ </fileset>
+ </family>
+
<family>
<nameset>
<name>serif</name>
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 6d29c69..92ecd24 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -61,7 +61,7 @@
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on March 3, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on April 1, 2014.
<br/>Any versions with less than 0.1% distribution are not shown.</em>
</p>
@@ -92,7 +92,7 @@
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on March 3, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on April 1, 2014.
<br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
@@ -133,17 +133,17 @@
</tr>
<tr>
<td>2.0</th>
-<td>91.1%</td>
+<td>89.4%</td>
</tr>
<tr>
<td>3.0</th>
-<td>8.8%</td>
+<td>10.5%</td>
</tr>
</table>
-<p style="clear:both"><em>Data collected during a 7-day period ending on March 3, 2014</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on April 1, 2014</em></p>
@@ -161,17 +161,17 @@
var VERSION_DATA =
[
{
- "chart": "//chart.googleapis.com/chart?chl=Froyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chd=t%3A1.2%2C19.0%2C0.1%2C15.2%2C62.0%2C2.5&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&chs=500x250&cht=p",
+ "chart": "//chart.googleapis.com/chart?cht=p&chs=500x250&chco=c4df9b%2C6fad0c&chf=bg%2Cs%2C00000000&chd=t%3A1.1%2C17.8%2C0.1%2C14.3%2C61.4%2C5.3&chl=Froyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat",
"data": [
{
"api": 8,
"name": "Froyo",
- "perc": "1.2"
+ "perc": "1.1"
},
{
"api": 10,
"name": "Gingerbread",
- "perc": "19.0"
+ "perc": "17.8"
},
{
"api": 13,
@@ -181,27 +181,27 @@
{
"api": 15,
"name": "Ice Cream Sandwich",
- "perc": "15.2"
+ "perc": "14.3"
},
{
"api": 16,
"name": "Jelly Bean",
- "perc": "35.3"
+ "perc": "34.4"
},
{
"api": 17,
"name": "Jelly Bean",
- "perc": "17.1"
+ "perc": "18.1"
},
{
"api": 18,
"name": "Jelly Bean",
- "perc": "9.6"
+ "perc": "8.9"
},
{
"api": 19,
"name": "KitKat",
- "perc": "2.5"
+ "perc": "5.3"
}
]
}
@@ -218,16 +218,15 @@
"Large": {
"hdpi": "0.6",
"ldpi": "0.7",
- "mdpi": "4.3",
+ "mdpi": "4.4",
"tvdpi": "1.5",
"xhdpi": "0.6"
},
"Normal": {
"hdpi": "33.7",
- "ldpi": "0.2",
- "mdpi": "13.6",
- "xhdpi": "19.9",
- "xxhdpi": "11.9"
+ "mdpi": "13.2",
+ "xhdpi": "19.8",
+ "xxhdpi": "12.5"
},
"Small": {
"ldpi": "8.1"
@@ -235,12 +234,12 @@
"Xlarge": {
"hdpi": "0.3",
"ldpi": "0.1",
- "mdpi": "4.3",
- "xhdpi": "0.2"
+ "mdpi": "4.2",
+ "xhdpi": "0.3"
}
},
- "densitychart": "//chart.googleapis.com/chart?chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chd=t%3A9.1%2C22.2%2C1.5%2C34.6%2C20.7%2C11.9&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&chs=400x250&cht=p",
- "layoutchart": "//chart.googleapis.com/chart?chl=Xlarge%7CLarge%7CNormal%7CSmall&chd=t%3A4.9%2C7.7%2C79.3%2C8.1&chf=bg%2Cs%2C00000000&chco=c4df9b%2C6fad0c&chs=400x250&cht=p"
+ "densitychart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b%2C6fad0c&chf=bg%2Cs%2C00000000&chd=t%3A8.9%2C21.8%2C1.5%2C34.6%2C20.7%2C12.6&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi",
+ "layoutchart": "//chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b%2C6fad0c&chf=bg%2Cs%2C00000000&chd=t%3A4.9%2C7.8%2C79.3%2C8.1&chl=Xlarge%7CLarge%7CNormal%7CSmall"
}
];
diff --git a/docs/html/design/index.jd b/docs/html/design/index.jd
index 9ba32dd..7c7c5d9 100644
--- a/docs/html/design/index.jd
+++ b/docs/html/design/index.jd
@@ -1,4 +1,5 @@
page.title=Design
+page.viewport_width=970
header.hide=1
footer.hide=1
@jd:body
diff --git a/docs/html/develop/index.jd b/docs/html/develop/index.jd
index 3f88b9d..eb28da8 100644
--- a/docs/html/develop/index.jd
+++ b/docs/html/develop/index.jd
@@ -1,5 +1,6 @@
fullpage=true
page.title=Develop
+page.viewport_width=970
header.hide=1
carousel=1
tabbedList=1
diff --git a/docs/html/distribute/index.jd b/docs/html/distribute/index.jd
index 544fdff..6c6e113 100644
--- a/docs/html/distribute/index.jd
+++ b/docs/html/distribute/index.jd
@@ -1,4 +1,5 @@
page.title=Distribute Apps
+page.viewport_width=970
header.hide=1
@jd:body
diff --git a/docs/html/google/index.jd b/docs/html/google/index.jd
index b743b66..2e97d62 100644
--- a/docs/html/google/index.jd
+++ b/docs/html/google/index.jd
@@ -125,7 +125,7 @@
<img src="{@docRoot}images/google/analytics.png" width="40" />
</div>
<h4><a class="external-link"
-href="https://developers.google.com/analytics/devguides/collection/android/v2/"
+href="https://developers.google.com/analytics/devguides/collection/android/v4/"
>Google Analytics</a></h4>
<p>Measure your success and gain insights into how users engage with your app content
diff --git a/docs/html/google/play-services/index.jd b/docs/html/google/play-services/index.jd
index 26b4ccc..5da0b75 100644
--- a/docs/html/google/play-services/index.jd
+++ b/docs/html/google/play-services/index.jd
@@ -71,7 +71,7 @@
</li>
<li><strong>Analytics</strong> - Google Analytics and Tag Manager are now part of Google Play services.
<ul>
- <li><a href="http://developers.google.com/analytics/devguides/collection/android/v3/" class="external-link">Getting Started with the Analytics API in Android</a></li>
+ <li><a href="http://developers.google.com/analytics/devguides/collection/android/v4/" class="external-link">Getting Started with the Analytics API in Android</a></li>
<li><a href="/reference/com/google/android/gms/analytics/package-summary.html">Analytics API reference</a></li>
<li><a href="http://developers.google.com/tag-manager/android/" class="external-link">Getting Started with the Tag Manager API in Android</a></li>
<li><a href="/reference/com/google/android/gms/tagmanager/package-summary.html">Tag Manager API reference</a></li>
diff --git a/docs/html/guide/components/intents-common.jd b/docs/html/guide/components/intents-common.jd
index 506cf9d..826dcff 100644
--- a/docs/html/guide/components/intents-common.jd
+++ b/docs/html/guide/components/intents-common.jd
@@ -11,6 +11,18 @@
<span class="less" style="display:none">show less</span></a></h2>
<ol id="tocIntents" class="hide-nested">
+ <li><a href="#Clock">Alarm Clock</a>
+ <ol>
+ <li><a href="#CreateAlarm">Create an alarm</a></li>
+ <li><a href="#CreateTimer">Create a timer</a></li>
+ <li><a href="#ShowAlarms">Show all alarms</a></li>
+ </ol>
+ </li>
+ <li><a href="#Calendar">Calendar</a>
+ <ol>
+ <li><a href="#AddEvent">Add a calendar event</a></li>
+ </ol>
+ </li>
<li><a href="#Camera">Camera</a>
<ol>
<li><a href="#ImageCapture">Capture a picture or video and return it</a></li>
@@ -116,6 +128,292 @@
+
+
+
+
+<h2 id="Clock">Alarm Clock</h2>
+
+
+<h3 id="CreateAlarm">Create an alarm</h3>
+
+<p>To create a new alarm, use the {@link android.provider.AlarmClock#ACTION_SET_ALARM}
+action and specify alarm details such as the time and message using extras defined below.</p>
+
+<p class="note"><strong>Note:</strong> Only the hour, minutes, and message extras are available
+since Android 2.3 (API level 9). The other extras were added in later versions of the platform.</p>
+
+<dl>
+<dt><b>Action</b></dt>
+<dd>{@link android.provider.AlarmClock#ACTION_SET_ALARM}</dd>
+
+<dt><b>Data URI</b></dt>
+<dd>None</dd>
+
+<dt><b>MIME Type</b></dt>
+<dd>None
+</dd>
+
+<dt><b>Extras</b></dt>
+<dd>
+ <dl>
+ <dt>{@link android.provider.AlarmClock#EXTRA_HOUR}</dt>
+ <dd>The hour for the alarm.</dd>
+ <dt>{@link android.provider.AlarmClock#EXTRA_MINUTES}</dt>
+ <dd>The minutes for the alarm.</dd>
+ <dt>{@link android.provider.AlarmClock#EXTRA_MESSAGE}</dt>
+ <dd>A custom message to identify the alarm.</dd>
+ <dt>{@link android.provider.AlarmClock#EXTRA_DAYS}</dt>
+ <dd>An {@link java.util.ArrayList} including each week day on which this alarm should
+ be repeated. Each day must be declared with an integer from the {@link java.util.Calendar}
+ class such as {@link java.util.Calendar#MONDAY}.
+ <p>For a one-time alarm, do not specify this extra.</dd>
+ <dt>{@link android.provider.AlarmClock#EXTRA_RINGTONE}</dt>
+ <dd>A {@code content:} URI specifying a ringtone to use with the alarm, or {@link
+ android.provider.AlarmClock#VALUE_RINGTONE_SILENT} for no ringtone.
+ <p>To use the default ringtone, do not specify this extra.</dd>
+ <dt>{@link android.provider.AlarmClock#EXTRA_VIBRATE}</dt>
+ <dd>A boolean specifying whether to vibrate for this alarm.</dd>
+ <dt>{@link android.provider.AlarmClock#EXTRA_SKIP_UI}</dt>
+ <dd>A boolean specifying whether the responding app should skip its UI when setting the alarm.
+ If true, the app should bypass any confirmation UI and simply set the specified alarm.</dd>
+ </dl>
+</dd>
+
+
+</dl>
+
+<p><b>Example intent:</b></p>
+<pre>
+public void createAlarm(String message, int hour, int minutes) {
+ Intent intent = new Intent(AlarmClock.ACTION_SET_ALARM)
+ .putExtra(AlarmClock.EXTRA_MESSAGE, message)
+ .putExtra(AlarmClock.EXTRA_HOUR, hour)
+ .putExtra(AlarmClock.EXTRA_MINUTES, minutes);
+ if (intent.resolveActivity(getPackageManager()) != null) {
+ startActivity(intent);
+ }
+}
+</pre>
+
+<div class="note"><strong>Note:</strong>
+<p>In order to invoke the {@link
+android.provider.AlarmClock#ACTION_SET_ALARM} intent, your app must have the
+{@link android.Manifest.permission#SET_ALARM} permission:</p>
+<pre>
+<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
+</pre>
+</div>
+
+
+<p><b>Example intent filter:</b></p>
+<pre>
+<activity ...>
+ <intent-filter>
+ <action android:name="android.intent.action.SET_ALARM" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+</activity>
+</pre>
+
+
+
+<h3 id="CreateTimer">Create a timer</h3>
+
+<p>To create a countdown timer, use the {@link android.provider.AlarmClock#ACTION_SET_TIMER}
+action and specify timer details such as the duration using extras defined below.</p>
+
+<p class="note"><strong>Note:</strong> This intent was added
+in Android 4.4 (API level 19).</p>
+
+<dl>
+<dt><b>Action</b></dt>
+<dd>{@link android.provider.AlarmClock#ACTION_SET_TIMER}</dd>
+
+<dt><b>Data URI</b></dt>
+<dd>None</dd>
+
+<dt><b>MIME Type</b></dt>
+<dd>None
+</dd>
+
+<dt><b>Extras</b></dt>
+<dd>
+ <dl>
+ <dt>{@link android.provider.AlarmClock#EXTRA_LENGTH}</dt>
+ <dd>The length of the timer in seconds.</dd>
+ <dt>{@link android.provider.AlarmClock#EXTRA_MESSAGE}</dt>
+ <dd>A custom message to identify the timer.</dd>
+ <dt>{@link android.provider.AlarmClock#EXTRA_SKIP_UI}</dt>
+ <dd>A boolean specifying whether the responding app should skip its UI when setting the timer.
+ If true, the app should bypass any confirmation UI and simply start the specified timer.</dd>
+ </dl>
+</dd>
+
+
+</dl>
+
+<p><b>Example intent:</b></p>
+<pre>
+public void startTimer(String message, int seconds) {
+ Intent intent = new Intent(AlarmClock.ACTION_SET_TIMER)
+ .putExtra(AlarmClock.EXTRA_MESSAGE, message)
+ .putExtra(AlarmClock.EXTRA_LENGTH, seconds)
+ .putExtra(AlarmClock.EXTRA_SKIP_UI, true);
+ if (intent.resolveActivity(getPackageManager()) != null) {
+ startActivity(intent);
+ }
+}
+</pre>
+
+<div class="note"><strong>Note:</strong>
+<p>In order to invoke the {@link
+android.provider.AlarmClock#ACTION_SET_TIMER} intent, your app must have the
+{@link android.Manifest.permission#SET_ALARM} permission:</p>
+<pre>
+<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
+</pre>
+</div>
+
+
+<p><b>Example intent filter:</b></p>
+<pre>
+<activity ...>
+ <intent-filter>
+ <action android:name="android.intent.action.SET_TIMER" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+</activity>
+</pre>
+
+
+
+
+
+<h3 id="ShowAlarms">Show all alarms</h3>
+
+<p>To show the list of alarms, use the {@link android.provider.AlarmClock#ACTION_SHOW_ALARMS}
+action.</p>
+
+<p>Although not many apps will invoke this intent (it's primarily used by system apps),
+any app that behaves as an alarm clock should implement
+this intent filter and respond by showing the list of current alarms.</p>
+
+<p class="note"><strong>Note:</strong> This intent was added
+in Android 4.4 (API level 19).</p>
+
+<dl>
+<dt><b>Action</b></dt>
+<dd>{@link android.provider.AlarmClock#ACTION_SHOW_ALARMS}</dd>
+
+<dt><b>Data URI</b></dt>
+<dd>None</dd>
+
+<dt><b>MIME Type</b></dt>
+<dd>None
+</dd>
+</dl>
+
+<p><b>Example intent filter:</b></p>
+<pre>
+<activity ...>
+ <intent-filter>
+ <action android:name="android.intent.action.SHOW_ALARMS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+</activity>
+</pre>
+
+
+
+
+
+
+<h2 id="Calendar">Calendar</h2>
+
+
+<h3 id="AddEvent">Add a calendar event</h3>
+
+<p>To add a new event to the user's calendar, use the {@link android.content.Intent#ACTION_INSERT}
+action and specify the data URI with {@link android.provider.CalendarContract.Events#CONTENT_URI
+Events.CONTENT_URI}. You can then specify various event details using extras defined below.</p>
+
+<dl>
+<dt><b>Action</b></dt>
+<dd>{@link android.content.Intent#ACTION_INSERT}</dd>
+
+<dt><b>Data URI</b></dt>
+<dd>{@link android.provider.CalendarContract.Events#CONTENT_URI
+Events.CONTENT_URI}</dd>
+
+<dt><b>MIME Type</b></dt>
+<dd>{@code "vnd.android.cursor.dir/event"}
+</dd>
+
+<dt><b>Extras</b></dt>
+<dd>
+ <dl>
+ <dt>{@link android.provider.CalendarContract#EXTRA_EVENT_ALL_DAY}</dt>
+ <dd>A boolean specifying whether this is an all-day event.</dd>
+ <dt>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME}</dt>
+ <dd>The start time of the event (milliseconds since epoch).</dd>
+ <dt>{@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME}</dt>
+ <dd>The end time of the event (milliseconds since epoch).</dd>
+ <dt>{@link android.provider.CalendarContract.EventsColumns#TITLE}</dt>
+ <dd>The event title.</dd>
+ <dt>{@link android.provider.CalendarContract.EventsColumns#DESCRIPTION}</dt>
+ <dd>The event description.</dd>
+ <dt>{@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION}</dt>
+ <dd>The event location.</dd>
+ <dt>{@link android.content.Intent#EXTRA_EMAIL}</dt>
+ <dd>A comma-separated list of email addresses that specify the invitees.</dd>
+ </dl>
+ <p>Many more event details can be specified using the constants defined in the
+ {@link android.provider.CalendarContract.EventsColumns} class.</p>
+</dd>
+
+
+</dl>
+
+<p><b>Example intent:</b></p>
+<pre>
+public void addEvent(String title, String location, Calendar begin, Calendar end) {
+ Intent intent = new Intent(Intent.ACTION_INSERT)
+ .setData(Events.CONTENT_URI)
+ .putExtra(Events.TITLE, title)
+ .putExtra(Events.EVENT_LOCATION, location)
+ .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, begin)
+ .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, end);
+ if (intent.resolveActivity(getPackageManager()) != null) {
+ startActivity(intent);
+ }
+}
+</pre>
+
+
+<p><b>Example intent filter:</b></p>
+<pre>
+<activity ...>
+ <intent-filter>
+ <action android:name="android.intent.action.INSERT" />
+ <data android:mimeType="vnd.android.cursor.dir/event" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+</activity>
+</pre>
+
+
+
+
+
+
+
+
+
+
+
+
+
<h2 id="Camera">Camera</h2>
@@ -211,6 +509,7 @@
+
<h2 id="Contacts">Contacts/People App</h2>
@@ -427,7 +726,7 @@
<dd>The type is inferred from contact URI.
</dd>
-<dt><b>Extras</b> (optional)</dt>
+<dt><b>Extras</b></dt>
<dd>One or more of the extras defined in {@link android.provider.ContactsContract.Intents.Insert}
so you can populate fields of the contact details.
</dd>
@@ -469,7 +768,7 @@
<dt><b>MIME Type</b></dt>
<dd>{@link android.provider.ContactsContract.Contacts#CONTENT_TYPE Contacts.CONTENT_TYPE}</dd>
-<dt><b>Extras</b> (optional)</dt>
+<dt><b>Extras</b></dt>
<dd>One or more of the extras defined in {@link android.provider.ContactsContract.Intents.Insert}.
</dd>
</dl>
@@ -523,7 +822,7 @@
</dl>
</dd>
-<dt><b>Extras</b> (optional)</dt>
+<dt><b>Extras</b></dt>
<dd>
<dl>
<dt>{@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL}</dt>
@@ -648,7 +947,7 @@
<dd>The MIME type corresponding to the file type the user should select.
</dd>
-<dt><b>Extras</b> (optional)</dt>
+<dt><b>Extras</b></dt>
<dd>
<dl>
<dt>{@link android.content.Intent#EXTRA_ALLOW_MULTIPLE}
@@ -768,7 +1067,7 @@
<dd>The MIME type corresponding to the file type the user should select.
</dd>
-<dt><b>Extras</b> (optional)</dt>
+<dt><b>Extras</b></dt>
<dd>
<dl>
<dt>{@link android.content.Intent#EXTRA_MIME_TYPES}
@@ -1139,7 +1438,7 @@
</dl>
</dd>
-<dt><b>Extras</b> (optional)</dt>
+<dt><b>Extras</b></dt>
<dd>
<dl>
<dt><code>"subject"</code></dt>
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 73d5b74..0a234aa 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -368,7 +368,10 @@
<span class="en">Media Playback</span></a>
</li>
<li><a href="<?cs var:toroot ?>guide/topics/media/mediarouter.html">
- <span class="en">MediaRouter</span></a>
+ <span class="en">Media Router</span></a>
+ </li>
+ <li><a href="<?cs var:toroot ?>guide/topics/media/mediarouteprovider.html">
+ <span class="en">Media Route Provider</span></a>
</li>
<li><a href="<?cs var:toroot ?>guide/appendix/media-formats.html">
<span class="en">Supported Media Formats</span></a>
diff --git a/docs/html/guide/topics/media/mediarouteprovider.jd b/docs/html/guide/topics/media/mediarouteprovider.jd
new file mode 100644
index 0000000..389fbfb
--- /dev/null
+++ b/docs/html/guide/topics/media/mediarouteprovider.jd
@@ -0,0 +1,453 @@
+page.title=Media Route Provider
+page.tags="mediarouteprovider","mediacontrolintent"
+@jd:body
+
+<div id="qv-wrapper">
+ <div id="qv">
+ <h2>In this document</h2>
+ <ol>
+ <li><a href="#overview">Overview</a>
+ <ol>
+ <li><a href="#dist">Distribution of route providers</a></li>
+ <li><a href="#playback-types">Types of playback</a></li>
+ <li><a href="#mr-packages">Media router packages</a></li>
+ </ol>
+ </li>
+ <li><a href="#provider-service">Creating a Provider Service</a></li>
+ <li><a href="#route-caps">Specifying Route Capabilities</a>
+ <ol>
+ <li><a href="#route-cat">Route categories</a></li>
+ <li><a href="#media-types">Media types and protocols</a></li>
+ <li><a href="#playback-ctrls">Playback controls</a></li>
+ <li><a href="#mrpd">MediaRouteProviderDescriptor</a></li>
+ </ol>
+ </li>
+ <li><a href="#ctrl-routes">Controlling Routes</a></li>
+ </ol>
+ <h2>Key Classes</h2>
+ <ol>
+ <li>{@link android.support.v7.media.MediaRouteProvider}</li>
+ <li>{@link android.support.v7.media.MediaRouteProviderDescriptor}</li>
+ <li>{@link android.support.v7.media.MediaRouteProvider.RouteController RouteController}</li>
+ </ol>
+ <h2>Related Samples</h2>
+ <ol>
+ <li><a href="{@docRoot}samples/MediaRouter/index.html">MediaRouter</a></li>
+ </ol>
+ </div>
+</div>
+
+<p>Users want to play media content from their Android devices bigger, brighter, and louder on
+ connected playback devices such as televisions, stereos,
+ and home theater equipment. As a manufacturer of these devices, allowing Android users to
+ instantly show a picture, play a song, or share a video for friends and family using your product
+ can make it much more compelling and engaging.</p>
+
+<p>The Android media router framework allows manufacturers to enable playback on their devices
+ through a standardized interface called a {@link android.support.v7.media.MediaRouteProvider}.
+ A route provider defines a common interface for playing media on a receiver device, making it
+ possible to play media on your equipment from any Android application that supports media
+ routes.</p>
+
+<p>This guide discusses how to create a media route provider for a receiver device and make it
+ available to other media playback applications that run on Android.</p>
+
+<h2 id="overview">Overview</h2>
+
+<p>The Android media router framework enables media app developers and media playback device
+ manufacturers to connect through a common API and common user interface. App developers that
+ implement a {@link android.support.v7.media.MediaRouter} interface can then connect to the
+ framework and play content to devices that participate in the media router framework. Media
+ playback device manufacturers can participate in the framework by publishing a {@link
+ android.support.v7.media.MediaRouteProvider} that allows other applications to connect to and
+ play media on the receiver devices. Figure 1 illustrates how an app connects to a receiving
+ device through the media router framework.</p>
+
+<img src="{@docRoot}images/mediarouter/media-route-provider-framework.png" alt="" id="figure1"/>
+<p class="img-caption">
+ <strong>Figure 1.</strong> Overview of how media route provider classes provide communication
+ from a media app to a receiver device.
+</p>
+
+<p>When you build a media route provider for your receiver device, the provider serves the
+following purposes:</p>
+
+<ul>
+ <li>Describe and publish the capabilities of the receiver device so other apps can discover it
+ and use its playback features.</li>
+ <li>Wrap the programming interface of the receiver device and its communication
+ transport mechanisms to make the device compatible with the media router framework.</li>
+</ul>
+
+
+<h3 id="dist">Distribution of route providers</h3>
+
+<p>A media route provider is distributed as part of an Android app. Your route provider can be
+ made available to other apps by extending
+ {@link android.support.v7.media.MediaRouteProviderService} or wrapping your implementation of
+ {@link android.support.v7.media.MediaRouteProvider} with your own service and declaring an intent
+ filter for the media route provider. These steps allow other apps to discover and make use of
+ your media route.</p>
+
+<p>
+ <strong>Note:</strong> The app containing the media route provider can also include a
+ <a href="{@docRoot}guide/topics/media/mediarouter.html">MediaRouter</a> interface to the
+ route provider, but this is not required.
+</p>
+
+
+<h3 id="playback-types">Types of playback</h3>
+
+<p>There are two main types of playback supported by the media router framework. A media route
+ provider can support one or both types of playback, depending on the capabilities of your playback
+ equipment and the functionality you want to support:</p>
+
+<ul>
+ <li><strong>Remote Playback</strong> — This approach uses the receiver device to handle the
+ content data retrieval, decoding, and playback, while an Android device in the user's hand is
+ used as a remote control. This approach is used by Android apps that support
+ <a href="https://developers.google.com/cast/">Google Cast</a>.</li>
+ <li><strong>Secondary Output</strong> — With this approach, the Android media application
+ retrieves, renders and streams video or music directly to the receiver device. This approach is
+ used to support Wireless Display output on Android.</li>
+</ul>
+
+
+<h3 id="mr-packages">Media router packages</h3>
+
+<p>
+ The media router APIs are provided as part of the Android Support Library version 18 and higher,
+ in the <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter">v7-mediarouter</a>
+ support library. You should use the classes in the
+ {@link android.support.v7.media} package for media route provider functions.
+ These APIs are compatible with devices running Android 2.1 (API level 7) and higher.
+</p>
+
+<p class="caution">
+ <strong>Caution:</strong> There is another set of media router APIs provided in the
+ {@link android.media} class package that have been superseded by the
+ <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter">v7-mediarouter</a>
+ support library. You <em>should not</em> use the {@link android.media} classes for
+ implementing media route provider functions.
+</p>
+
+<p>In order to use the {@link android.support.v7.media} media router classes, you
+ must add the <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter"
+ >v7-mediarouter support library package</a> to your app development project. For more
+ information on adding support libraries to your app development project, see
+ <a href="{@docRoot}tools/support-library/setup.html">Support Library Setup</a>.
+</p>
+
+
+<h2 id="provider-service">Creating a Provider Service</h2>
+
+<p>The media router framework must be able to discover and connect to your media route provider
+ to allow other applications to use your route. In order to do this, the media router framework
+ looks for apps that declare a media route provider intent action. When another app wants to
+ connect to your provider, the framework must be able to invoke and connect to it, so your provider
+ must be encapsulated in a {@link android.app.Service}.</p>
+
+<p>The following example code shows the declaration of a media route provider service and the
+ intent filter in a manifest, which allows it to be discovered and used by the media router
+ framework:</p>
+
+<pre>
+<service android:name=".provider.SampleMediaRouteProviderService"
+ android:label="@string/sample_media_route_provider_service"
+ android:process=":mrp">
+ <intent-filter>
+ <action android:name="android.media.MediaRouteProviderService" />
+ </intent-filter>
+</service>
+</pre>
+
+<p>This manifest example declares a service that wraps the actual media route provider classes.
+ The Android media router framework provides the
+ {@link android.support.v7.media.MediaRouteProviderService} class for use as a service wrapper for
+ media route providers. The following example code demonstrates how to use this wrapper
+ class:</p>
+
+<pre>
+public class SampleMediaRouteProviderService extends MediaRouteProviderService {
+
+ @Override
+ public MediaRouteProvider onCreateMediaRouteProvider() {
+ return new SampleMediaRouteProvider(this);
+ }
+}
+</pre>
+
+
+<h2 id="route-caps">Specifying Route Capabilities</h2>
+
+<p>Apps connecting to the media router framework can discover your media route through your
+ app's manifest declarations, but they also need to know the capabilities of the media routes you
+ are providing. Media routes can be of different types and have different features, and other apps
+ need to be able to discover these details to determine if they are compatible with your route.</p>
+
+<p>The media router framework allows you to define and publish the capabilities of your media
+ route through {@link android.content.IntentFilter} objects, {@link
+ android.support.v7.media.MediaRouteDescriptor} objects and a {@link
+ android.support.v7.media.MediaRouteProviderDescriptor}. This section explains how to use these
+ classes to publish the details of your media route for other apps.</p>
+
+
+<h3 id="route-cat">Route categories</h3>
+
+<p>As part of the programmatic description of your media route provider, you must specify
+ whether your provider supports remote playback, secondary output, or both. These are the route
+ categories provided by the media router framework:</p>
+
+<ul>
+ <li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_LIVE_AUDIO CATEGORY_LIVE_AUDIO}
+ — Output of audio to a secondary output device, such as a wireless-enabled music system.
+ </li>
+ <li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_LIVE_VIDEO CATEGORY_LIVE_VIDEO}
+ — Output of video to a secondary output device, such as Wireless Display devices.</li>
+ <li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_REMOTE_PLAYBACK
+ CATEGORY_REMOTE_PLAYBACK} — Play video or audio on a separate device which handles media
+ retrieval, decoding, and playback, such as
+ <a href="https://www.google.com/url?q=http://www.google.com/chromecast">Chromecast</a> devices.
+ </li>
+</ul>
+
+<p>In order to include these settings in a description of your media route, you insert them into
+ an {@link android.content.IntentFilter} object, which you later add to a
+ {@link android.support.v7.media.MediaRouteDescriptor} object:</p>
+
+<pre>
+public final class SampleMediaRouteProvider extends MediaRouteProvider {
+ private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;
+ static {
+ IntentFilter videoPlayback = new IntentFilter();
+ <strong>videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);</strong>
+ CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
+ CONTROL_FILTERS_BASIC.add(videoPlayback);
+ }
+}
+
+</pre>
+
+<p>If you specify the {@link android.support.v7.media.MediaControlIntent#CATEGORY_REMOTE_PLAYBACK
+ CATEGORY_REMOTE_PLAYBACK} intent, you must also define what media types and
+ playback controls are supported by your media route provider. The next section describes how to
+ specify these settings for your device.</p>
+
+
+<h3 id="media-types">Media types and protocols</h3>
+
+<p>A media route provider for a remote playback device must specify the media types and transfer
+ protocols it supports. You specify these settings using the {@link android.content.IntentFilter}
+ class and the {@link android.content.IntentFilter#addDataScheme addDataScheme()} and
+ {@link android.content.IntentFilter#addDataType addDataType()} methods of that object. The
+ following code snippet demonstrates how to define an intent filter for supporting remote video
+ playback using http, https, and Real Time Streaming Protocol (RTSP):</p>
+
+<pre>
+public final class SampleMediaRouteProvider extends MediaRouteProvider {
+
+ private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;
+
+ static {
+ IntentFilter videoPlayback = new IntentFilter();
+ videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+ videoPlayback.addAction(MediaControlIntent.ACTION_PLAY);
+ videoPlayback.addDataScheme("http");
+ videoPlayback.addDataScheme("https");
+ videoPlayback.addDataScheme("rtsp");
+ addDataTypeUnchecked(videoPlayback, "video/*");
+ CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
+ CONTROL_FILTERS_BASIC.add(videoPlayback);
+ }
+ ...
+
+ private static void addDataTypeUnchecked(IntentFilter filter, String type) {
+ try {
+ filter.addDataType(type);
+ } catch (MalformedMimeTypeException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+}
+
+</pre>
+
+
+<h3 id="playback-ctrls">Playback controls</h3>
+
+<p>A media route provider that offers remote playback must specify the types of media controls
+ it supports. These are the general types of control that media routes can provide:</p>
+
+<ul>
+ <li><strong>Playback controls</strong>, such as play, pause, rewind, and fast-forward.</li>
+ <li><strong>Queuing features</strong>, which allow the sending app to add and remove items
+ from a playlist which is maintained by the receiver device.</li>
+ <li><strong>Session features</strong>, which prevent sending apps from interfering with each
+ other by having the receiver device provide a session id to the requesting app and then checking
+ that id with each subsequent playback control request.</li>
+</ul>
+
+<p>The following code example demonstrates how to construct an intent filter for supporting
+ basic media route playback controls:</p>
+
+<pre>
+public final class SampleMediaRouteProvider extends MediaRouteProvider {
+ private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;
+ static {
+ ...
+ IntentFilter playControls = new IntentFilter();
+ playControls.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
+ playControls.addAction(MediaControlIntent.ACTION_SEEK);
+ playControls.addAction(MediaControlIntent.ACTION_GET_STATUS);
+ playControls.addAction(MediaControlIntent.ACTION_PAUSE);
+ playControls.addAction(MediaControlIntent.ACTION_RESUME);
+ playControls.addAction(MediaControlIntent.ACTION_STOP);
+ CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
+ CONTROL_FILTERS_BASIC.add(videoPlayback);
+ CONTROL_FILTERS_BASIC.add(playControls);
+ }
+ ...
+}
+</pre>
+
+<p>For more information about the available playback control intents, see the
+ {@link android.support.v7.media.MediaControlIntent} class.</p>
+
+
+<h3 id="mrpd">MediaRouteProviderDescriptor</h3>
+
+<p>After defining the capabilities of your media route using {@link
+ android.content.IntentFilter} objects, you can then create a descriptor object for publishing to
+ the Android media router framework. This descriptor object contains the specifics of your media
+ route's capabilities so that other applications can determine how to interact with your media
+ route.</p>
+
+<p>The following example code demonstrates how to add the previously created intent filters to a
+ {@link android.support.v7.media.MediaRouteProviderDescriptor} and set the descriptor for use by
+ the media router framework:</p>
+
+<pre>
+public SampleMediaRouteProvider(Context context) {
+ super(context);
+ publishRoutes();
+}
+
+private void publishRoutes() {
+ Resources r = getContext().getResources();
+ // Create a route descriptor using previously created IntentFilters
+ MediaRouteDescriptor routeDescriptor = new MediaRouteDescriptor.Builder(
+ VARIABLE_VOLUME_BASIC_ROUTE_ID,
+ r.getString(R.string.variable_volume_basic_route_name))
+ .setDescription(r.getString(R.string.sample_route_description))
+ .addControlFilters(CONTROL_FILTERS_BASIC)
+ .setPlaybackStream(AudioManager.STREAM_MUSIC)
+ .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
+ .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
+ .setVolumeMax(VOLUME_MAX)
+ .setVolume(mVolume)
+ .build();
+ // Add the route descriptor to the provider descriptor
+ MediaRouteProviderDescriptor providerDescriptor =
+ new MediaRouteProviderDescriptor.Builder()
+ .addRoute(routeDescriptor)
+ .build();
+
+ // Publish the descriptor to the framework
+ setDescriptor(providerDescriptor);
+}
+</pre>
+
+<p>For more information on the available descriptor settings, see the reference documentation
+ for {@link android.support.v7.media.MediaRouteDescriptor} and {@link
+ android.support.v7.media.MediaRouteProviderDescriptor}.</p>
+
+
+<h2 id="ctrl-routes">Controlling Routes</h2>
+
+<p>When an application connects to your media route provider, the provider receives playback
+ commands through the media router framework sent to your route by other apps. To handle these
+ requests, you must provide an implementation of a {@link
+ android.support.v7.media.MediaRouteProvider.RouteController} class, which processes the commands
+ and handles the actual communication to your receiver device.</p>
+
+<p>The media router framework calls the {@link
+ android.support.v7.media.MediaRouteProvider#onCreateRouteController onCreateRouteController()}
+ method of your route provider to obtain an instance of this class and then routes requests to it.
+ These are the key methods of the {@link
+ android.support.v7.media.MediaRouteProvider.RouteController} class, which you must implement for
+ your media route provider:</p>
+
+<ul>
+ <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onSelect onSelect()}
+ — Called when an application selects your route for playback. You use this method to do
+ any preparation work that may be required before media playback begins.</li>
+ <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onControlRequest
+ onControlRequest()} — Sends specific playback commands to the receiving device.</li>
+ <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onSetVolume
+ onSetVolume()} — Sends a request to the receiving device to set the playback volume to a
+ specific value.</li>
+ <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onUpdateVolume
+ onUpdateVolume()} — Sends a request to the receiving device to modify the playback
+ volume by a specified amount.</li>
+ <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onUnselect
+ onUnselect()} — Called when an application unselects a route.</li>
+ <li>{@link android.support.v7.media.MediaRouteProvider.RouteController#onRelease onRelease()}
+ — Called when the route is no longer needed by the framework, allowing it to free its
+ resources.</li>
+</ul>
+
+<p>All playback control requests, except for volume changes, are directed to the {@link
+ android.support.v7.media.MediaRouteProvider.RouteController#onControlRequest onControlRequest()}
+ method. Your implementation of this method must parse the control requests and respond to them
+ appropriately. Here is an example implementation of this method which processes commands for a
+ remote playback media route:</p>
+
+<pre>
+private final class SampleRouteController extends
+ MediaRouteProvider.RouteController {
+ ...
+
+ @Override
+ public boolean onControlRequest(Intent intent, ControlRequestCallback callback) {
+
+ String action = intent.getAction();
+
+ if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
+ boolean success = false;
+ if (action.equals(MediaControlIntent.ACTION_PLAY)) {
+ success = handlePlay(intent, callback);
+ } else if (action.equals(MediaControlIntent.ACTION_ENQUEUE)) {
+ success = handleEnqueue(intent, callback);
+ } else if (action.equals(MediaControlIntent.ACTION_REMOVE)) {
+ success = handleRemove(intent, callback);
+ } else if (action.equals(MediaControlIntent.ACTION_SEEK)) {
+ success = handleSeek(intent, callback);
+ } else if (action.equals(MediaControlIntent.ACTION_GET_STATUS)) {
+ success = handleGetStatus(intent, callback);
+ } else if (action.equals(MediaControlIntent.ACTION_PAUSE)) {
+ success = handlePause(intent, callback);
+ } else if (action.equals(MediaControlIntent.ACTION_RESUME)) {
+ success = handleResume(intent, callback);
+ } else if (action.equals(MediaControlIntent.ACTION_STOP)) {
+ success = handleStop(intent, callback);
+ } else if (action.equals(MediaControlIntent.ACTION_START_SESSION)) {
+ success = handleStartSession(intent, callback);
+ } else if (action.equals(MediaControlIntent.ACTION_GET_SESSION_STATUS)) {
+ success = handleGetSessionStatus(intent, callback);
+ } else if (action.equals(MediaControlIntent.ACTION_END_SESSION)) {
+ success = handleEndSession(intent, callback);
+ }
+
+ Log.d(TAG, mSessionManager.toString());
+ return success;
+ }
+ return false;
+ }
+ ...
+}
+</pre>
+
+<p>It is important to understand that the {@link
+ android.support.v7.media.MediaRouteProvider.RouteController} class is intended to act as a wrapper
+ for the API to your media playback equipment. The implementation of the methods in this class is
+ entirely dependent on the programmatic interface provided by your receiving device.</p>
diff --git a/docs/html/guide/topics/media/mediarouter.jd b/docs/html/guide/topics/media/mediarouter.jd
index 1b10265..e0bf889 100644
--- a/docs/html/guide/topics/media/mediarouter.jd
+++ b/docs/html/guide/topics/media/mediarouter.jd
@@ -1,5 +1,5 @@
-page.title=MediaRouter
-page.tags="cast","chromecast","wireless display","miracast"
+page.title=Media Router
+page.tags="mediarouter","cast","chromecast","wireless display","miracast"
@jd:body
<div id="qv-wrapper">
@@ -36,6 +36,10 @@
<li>{@link android.support.v7.media.MediaRouter.Callback}</li>
<li>{@link android.support.v7.media.MediaRouteProvider}</li>
</ol>
+ <h2>Related Samples</h2>
+ <ol>
+ <li><a href="{@docRoot}guide/topics/media/mediarouter.html">MediaRouter</a></li>
+ </ol>
</div>
</div>
@@ -105,15 +109,17 @@
(API level 7) and higher.
</p>
-<p class="note">
- <strong>Note:</strong> There is another set of media router APIs provided in the
+<p class="caution">
+ <strong>Caution:</strong> There is another set of media router APIs provided in the
{@link android.media} that have been superseded by the v7-mediarouter support library.
You <em>should not</em> use the {@link android.media} classes for media router functions.
</p>
<p>In order to use the {@link android.support.v7.media} media router classes, you must add
the <a href="{@docRoot}tools/support-library/features.html#v7-mediarouter">v7-mediarouter
- support library package</a> to your app development project.
+ support library package</a> to your app development project. For more
+ information on adding support libraries to your app development project, see
+ <a href="{@docRoot}tools/support-library/setup.html">Support Library Setup</a>.
</p>
@@ -211,9 +217,9 @@
CATEGORY_LIVE_VIDEO} — Output of video to a secondary output device, such as Wireless
Display devices.</li>
<li>{@link android.support.v7.media.MediaControlIntent#CATEGORY_REMOTE_PLAYBACK
- CATEGORY_REMOTE_PLAYBACK} — Play video or audio on a separate device that supports the
- <a href="https://developers.google.com/cast/">Google Cast</a> remote control protocol, such
- as <a href="https://www.google.com/url?q=http://www.google.com/chromecast">Chromecast</a>.
+ CATEGORY_REMOTE_PLAYBACK} — Play video or audio on a separate device that handles media
+ retrieval, decoding, and playback, such as
+ <a href="https://www.google.com/url?q=http://www.google.com/chromecast">Chromecast</a> devices.
</li>
</ul>
@@ -279,7 +285,7 @@
<p>In order to connect to a media route selected by the user, your app must obtain the {@link
android.support.v7.media.MediaRouter} framework object and then attach a {@link
android.support.v7.media.MediaRouter.Callback} object. The callback object receives messages
- from the media router framework when a route selected, changed or disconnected by the user.</p>
+ from the media router framework when a route is selected, changed, or disconnected by the user.</p>
<p>To obtain an instance of the {@link android.support.v7.media.MediaRouter} framework object,
call {@link android.support.v7.media.MediaRouter#getInstance MediaRouter.getInstance()}
@@ -299,11 +305,11 @@
<p>The media router framework communicates with an app through a callback object that
you attach to the {@link android.support.v7.media.MediaRouter} framework object. An app
that uses the media router framework must extend the {@link
- android.support.v7.media.MediaRouter.Callback} object to receive messages when a media route is
- connected and provide content to the connected device through that route.</p>
+ android.support.v7.media.MediaRouter.Callback} object in order to receive messages when a
+ media route is connected.</p>
-<p>There are several methods in the callback that can be overwritten to receive messages about
- media router events. At the minimum, your implementation of the {@link
+<p>There are several methods in the callback that you can override to receive information about
+ media router events. At minimum, your implementation of the {@link
android.support.v7.media.MediaRouter.Callback} class should override the following
methods:</p>
@@ -440,12 +446,12 @@
<p class="note">
<strong>Note:</strong> The media route framework also provides a
- {@link android.support.v7.app.MediaRouteDiscoveryFragment} class which takes care of adding and
- removing the call back for an activity.
+ {@link android.support.v7.app.MediaRouteDiscoveryFragment} class, which takes care of adding and
+ removing the callback for an activity.
</p>
<p>Now when you run your application, you should see a Cast button appear in your activity.
- When you press the button the media router framework, a route selection dialog appears as shown
+ When you touch the button, a route selection dialog appears as shown
in figure 3, allowing your user to select an available media route. Make sure you have a
supported device available on your local network when testing this interface.</p>
diff --git a/docs/html/images/mediarouter/media-route-provider-framework.png b/docs/html/images/mediarouter/media-route-provider-framework.png
new file mode 100644
index 0000000..60cc29a
--- /dev/null
+++ b/docs/html/images/mediarouter/media-route-provider-framework.png
Binary files differ
diff --git a/docs/html/images/tools/as-buildvariants.png b/docs/html/images/tools/as-buildvariants.png
new file mode 100644
index 0000000..a245163
--- /dev/null
+++ b/docs/html/images/tools/as-buildvariants.png
Binary files differ
diff --git a/docs/html/images/tools/as-demoflavordirs.png b/docs/html/images/tools/as-demoflavordirs.png
new file mode 100644
index 0000000..9d36a6d
--- /dev/null
+++ b/docs/html/images/tools/as-demoflavordirs.png
Binary files differ
diff --git a/docs/html/images/tools/as-gradlebutton.png b/docs/html/images/tools/as-gradlebutton.png
new file mode 100644
index 0000000..091b935
--- /dev/null
+++ b/docs/html/images/tools/as-gradlebutton.png
Binary files differ
diff --git a/docs/html/images/tools/as-gradleconsole.png b/docs/html/images/tools/as-gradleconsole.png
new file mode 100644
index 0000000..c676c94
--- /dev/null
+++ b/docs/html/images/tools/as-gradleconsole.png
Binary files differ
diff --git a/docs/html/images/tools/as-gradlepanel.png b/docs/html/images/tools/as-gradlepanel.png
new file mode 100644
index 0000000..a409462
--- /dev/null
+++ b/docs/html/images/tools/as-gradlepanel.png
Binary files differ
diff --git a/docs/html/images/tools/as-gradlesync.png b/docs/html/images/tools/as-gradlesync.png
new file mode 100644
index 0000000..b312359
--- /dev/null
+++ b/docs/html/images/tools/as-gradlesync.png
Binary files differ
diff --git a/docs/html/images/tools/as-mainscreen.png b/docs/html/images/tools/as-mainscreen.png
new file mode 100644
index 0000000..da399d7
--- /dev/null
+++ b/docs/html/images/tools/as-mainscreen.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index baeaa5b..99a469a 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -1,4 +1,5 @@
fullpage=true
+page.viewport_width=970
no_footer_links=true
carousel=true
excludeFromSuggestions=true
@@ -20,7 +21,7 @@
<li class="item carousel-home">
<div class="content-left col-10" style="width:580px;">
- <a href="{@docRoot}design/patterns/new.html">
+ <a href="{@docRoot}wear/index.html">
<img src="{@docRoot}images/home/aw_dac.png" style="margin-top:50px" >
</a>
</div>
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 8bb75df..e7f78e8 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -4,44 +4,45 @@
header.hide=1
page.metaDescription=Download the official Android SDK to develop apps for Android-powered devices.
+sdk.version=22.6.2
-sdk.linux32_bundle_download=adt-bundle-linux-x86-20131030.zip
-sdk.linux32_bundle_bytes=496876498
-sdk.linux32_bundle_checksum=d389139ad9f59a43bdd34c94bc850509
+sdk.linux32_bundle_download=adt-bundle-linux-x86-20140321.zip
+sdk.linux32_bundle_bytes=527971926
+sdk.linux32_bundle_checksum=943ae4d28fe7c79108c8bf2aafd5e6d2
-sdk.linux64_bundle_download=adt-bundle-linux-x86_64-20131030.zip
-sdk.linux64_bundle_bytes=497171697
-sdk.linux64_bundle_checksum=99b51a4f0526434b083701a896550b72
+sdk.linux64_bundle_download=adt-bundle-linux-x86_64-20140321.zip
+sdk.linux64_bundle_bytes=528187678
+sdk.linux64_bundle_checksum=f2a2153b5c7dbaeb86b550bf4f770c36
-sdk.mac64_bundle_download=adt-bundle-mac-x86_64-20131030.zip
-sdk.mac64_bundle_bytes=470386961
-sdk.mac64_bundle_checksum=3e80e7a92b549029d91bdcf2ae82657f
+sdk.mac64_bundle_download=adt-bundle-mac-x86_64-20140321.zip
+sdk.mac64_bundle_bytes=501955296
+sdk.mac64_bundle_checksum=4a08649cea9b098cdf7349f452294014
-sdk.win32_bundle_download=adt-bundle-windows-x86-20131030.zip
-sdk.win32_bundle_bytes=503599460
-sdk.win32_bundle_checksum=cd490a531ec24667354f6473e999b988
+sdk.win32_bundle_download=adt-bundle-windows-x86-20140321.zip
+sdk.win32_bundle_bytes=535085536
+sdk.win32_bundle_checksum=b61495a6bf591cc374c31bce4fc46ec0
-sdk.win64_bundle_download=adt-bundle-windows-x86_64-20131030.zip
-sdk.win64_bundle_bytes=503735416
-sdk.win64_bundle_checksum=ddddbb1b9028015779d68dde01f96b14
+sdk.win64_bundle_download=adt-bundle-windows-x86_64-20140321.zip
+sdk.win64_bundle_bytes=535287324
+sdk.win64_bundle_checksum=a6f4699bbdc5a29b371ed60610535651
-sdk.linux_download=android-sdk_r22.6.1-linux.tgz
-sdk.linux_bytes=101052129
-sdk.linux_checksum=d95b400600e9b68ed7719e0fd1792e0b
+sdk.linux_download=android-sdk_r22.6.2-linux.tgz
+sdk.linux_bytes=101050024
+sdk.linux_checksum=ff1541418a44d894bedc5cef10622220
-sdk.mac_download=android-sdk_r22.6.1-macosx.zip
-sdk.mac_bytes=74639176
-sdk.mac_checksum=99abc850398ccc220e3a1d6d0ab73ccf
+sdk.mac_download=android-sdk_r22.6.2-macosx.zip
+sdk.mac_bytes=74639394
+sdk.mac_checksum=2a319c862dd1dcf450bfe2a6b3d9c608
-sdk.win_download=android-sdk_r22.6.1-windows.zip
-sdk.win_bytes=108914728
-sdk.win_checksum=88471340a8c99822ffb5efbe3c28167c
+sdk.win_download=android-sdk_r22.6.2-windows.zip
+sdk.win_bytes=108917505
+sdk.win_checksum=6e5bfdb7b9c1d231ed6ec78b31551cbf
-sdk.win_installer=installer_r22.6.1-windows.exe
-sdk.win_installer_bytes=88907175
-sdk.win_installer_checksum=fd664527ed1b1b1bfe2d4546cafc7ada
+sdk.win_installer=installer_r22.6.2-windows.exe
+sdk.win_installer_bytes=87383126
+sdk.win_installer_checksum=2a68b8b22ecd0aba779b1581a914b395
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index 42cb92c..e4cf1bc 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -1,8 +1,8 @@
page.title=Installing the Eclipse Plugin
-adt.zip.version=22.6.0
-adt.zip.download=ADT-22.6.0.zip
-adt.zip.bytes=14585211
-adt.zip.checksum=d95c6d8e678881f6c89f063b58d4162f
+adt.zip.version=22.6.2
+adt.zip.download=ADT-22.6.2.zip
+adt.zip.bytes=14586842
+adt.zip.checksum=f660959fa71262b4285bcb64be284bf5
@jd:body
@@ -35,10 +35,10 @@
<li>In the Add Repository dialog that appears, enter "ADT Plugin" for the <em>Name</em> and the
following URL for the <em>Location</em>:
<pre>https://dl-ssl.google.com/android/eclipse/</pre>
+ <p class="note"><strong>Note:</strong> The Android Developer Tools update site requires
+ a secure connection. Make sure the update site URL you enter starts with HTTPS.</p>
</li>
- <li>Click <strong>OK</strong>.
- <p>If you have trouble acquiring the plugin, try using "http" in the Location URL,
-instead of "https" (https is preferred for security reasons).</p></li>
+ <li>Click <strong>OK</strong>.</li>
<li>In the Available Software dialog, select the checkbox next to Developer Tools and click
<strong>Next</strong>.</li>
<li>In the next window, you'll see a list of the tools to be downloaded. Click
@@ -75,7 +75,7 @@
<div class="sidebox-wrapper">
<div class="sidebox">
<h2>App Translations in Google Play</h2>
-<p>Google Play <a href="{@docRoot}distribute/googleplay/publish/localizing.html#gp-trans">App
+<p>Google Play <a href="{@docRoot}distribute/googleplay/publish/localizing.html#gp-trans">App
Translation Service</a> is available in the Developer Console to help you
localize your app for a global user base. You can browse qualified vendors, get
estimates, upload strings for translation, and then import the translations directly
@@ -139,23 +139,16 @@
<h2 id="Troubleshooting">Troubleshooting ADT Installation</h2>
-<p> If you are having trouble downloading the ADT plugin after following the
-steps above, here are some suggestions: </p>
-
-<ul>
- <li>If Eclipse can not find the remote update site containing the ADT plugin,
-try changing the remote site URL to use http, rather than https. That is, set
-the Location for the remote site to:
-<pre>http://dl-ssl.google.com/android/eclipse/</pre></li>
-<li>If you are behind a firewall (such as a corporate firewall), make sure that
+<p>If you are having trouble downloading the ADT plugin after following the
+steps above and you are behind a firewall (such as a corporate firewall), make sure that
you have properly configured your proxy settings in Eclipse. In Eclipse,
you can configure proxy information from the main Eclipse menu in
<strong>Window</strong> (on Mac OS X, <strong>Eclipse</strong>) >
<strong>Preferences</strong> > <strong>General</strong> > <strong>Network
-Connections</strong>.</li>
-</ul>
+Connections</strong>.
+</p>
-<p> If you are still unable to use Eclipse to download the ADT plugin as a
+<p>If you are still unable to use Eclipse to download the ADT plugin as a
remote update site, you can download the ADT zip file to your local machine and
manually install it:</p>
diff --git a/docs/html/sdk/installing/studio-build.jd b/docs/html/sdk/installing/studio-build.jd
new file mode 100644
index 0000000..8674134
--- /dev/null
+++ b/docs/html/sdk/installing/studio-build.jd
@@ -0,0 +1,1065 @@
+page.title=Building Your Project with Gradle
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>In this document</h2>
+<ol>
+ <li><a href="#overviewBuild">Overview of the Build System</a>
+ <ol>
+ <li><a href="#buildConf">Build configuration</a></li>
+ <li><a href="#buildConv">Build by convention</a></li>
+ <li><a href="#projectModules">Projects and modules</a></li>
+ <li><a href="#dependencies">Dependencies</a></li>
+ <li><a href="#buildTasks">Build tasks</a></li>
+ <li><a href="#gradleWrapper">The Gradle wrapper</a></li>
+ </ol>
+ </li>
+ <li><a href="#creatingBuilding">Create and Build a Project</a>
+ <ol>
+ <li><a href="#createProject">Create a project</a></li>
+ <li><a href="#projectStructure">Project structure</a></li>
+ <li><a href="#addLibModule">Add a library module</a></li>
+ <li><a href="#buildProject">Build the project</a></li>
+ <li><a href="#buildCmd">Build from the command line</a></li>
+ </ol>
+ </li>
+ <li><a href="#configBuild">Configure the Build</a>
+ <ol>
+ <li><a href="#buildFileBasics">Build file basics</a></li>
+ <li><a href="#declareDeps">Declare dependencies</a></li>
+ <li><a href="#runProguard">Run ProGuard</a></li>
+ <li><a href="#configureSigning">Configure signing settings</a></li>
+ <li><a href="#workBuildVariants">Work with build variants</a></li>
+ </ol>
+ </li>
+ <li><a href="#reference">Reference</a></li>
+</ol>
+<h2>See also</h2>
+<ul>
+<li><a href="{@docRoot}sdk/installing/studio.html">
+Getting Started with Android Studio</a></li>
+<li><a href="{@docRoot}sdk/installing/studio-tips.html">
+Android Studio Tips and Tricks</a></li>
+<li><a href="{@docRoot}sdk/installing/migrate.html">
+Migrating from Eclipse</a></li>
+</div>
+</div>
+
+<a class="notice-developers-video"
+href="https://developers.google.com/events/io/sessions/324603352">
+<div>
+ <h3>Video</h3>
+ <p>What's New in Android Developer Tools</p>
+</div>
+</a>
+
+<p>The Android Studio build system is the toolkit you use to build, test, run and package
+your apps. The build system is independent from Android Studio, so you can invoke it from Android
+Studio or from the command line. After you write your application, you can use the features
+of the build system to:</p>
+
+<ul>
+ <li>Customize, configure, and extend the build process.</li>
+ <li>Create multiple APKs for your app with different features using the same project.</li>
+ <li>Reuse code and resources.</li>
+</ul>
+
+<p>The flexibility of the Android Studio build system enables you to achieve all of this without
+modifying your app's core project files.</p>
+
+
+<h2 id="overviewBuild">Overview of the Build System</h2>
+
+<p>The Android Studio build system consists of an Android plugin for <em>Gradle</em>.
+<a href="http://www.gradle.org/">Gradle</a> is an advanced build toolkit that manages dependencies
+and allows you to define custom build logic. Many software projects use Gradle to manage their
+builds. The Android plugin for Gradle does not depend on Android Studio, although Android Studio
+is fully integrated with it. This means that:</p>
+
+<ul>
+ <li>You can build your Android apps from the command line on your machine or on machines
+ where Android Studio is not installed (such as continuous integration servers).</li>
+ <li>You can build your Android apps from Android Studio with the same custom build
+ configuration and logic as when you build from the command line.</li>
+</ul>
+
+<p>The output of the build is the same whether you are building a project from the command line,
+on a remote machine, or using Android Studio.</p>
+
+<h3 id="buildConf">Build configuration</h3>
+
+<p>The build configuration for your project is defined inside <em>Gradle build files</em>,
+which are plain text files that use the syntax and options from Gradle and the Android plugin
+to configure the following aspects of your build:</p>
+
+<ul>
+ <li><em>Build variants</em>. The build system can generate multiple APKs with different
+ configurations for the same project. This is useful when you want to build different
+ versions of your application without having to create a separate project for each of
+ them.</li>
+ <li><em>Dependencies</em>. The build system manages project dependencies and supports
+ dependencies from your local filesystem and from remote repositories. This prevents you
+ from having to search, download, and copy binary packages for your dependencies into your
+ project directory.</li>
+ <li><em>Manifest entries</em>. The build system enables you to specify values for some
+ elements of the manifest file in the build configuration. These new values override the
+ existing values in the manifest file. This is useful if you want to generate multiple APKs
+ for your project where each of them has a different package name, minimum SDK version, or
+ target SDK version.</li>
+ <li><em>Signing</em>. The build system enables you to specify signing settings in the build
+ configuration, and it can sign your APKs during the build process.</li>
+ <li><em>ProGuard</em>. The build system enables you to specify a different
+ <a href="{@docRoot}tools/help/proguard.html">ProGuard</a> rules
+ file for each build variant. The build system can run ProGuard to obfuscate your classes
+ during the build process.</li>
+ <li><em>Testing</em>. The build system generates a test APK from the test sources in your
+ project, so you do not have to create a separate test project. The build system can run
+ your tests during the build process.</li>
+</ul>
+
+<p>Gradle build files use <em>Groovy</em> syntax.
+<a href="http://groovy.codehaus.org/">Groovy</a> is a dynamic language that you can use to
+define custom build logic and to interact with the Android-specific elements provided by the
+Android plugin for Gradle.</p>
+
+<h3 id="buildConv">Build by convention</h3>
+
+<p>The Android Studio build system assumes <em>sensible defaults</em> for the project structure
+and other build options. If your project adheres to these conventions, your Gradle build files are
+very simple. When some these conventions do not apply to your project, the flexibility of the
+build system allows you to configure almost every aspect of the build process. For example, if
+the sources for your project are located in a different directory than the default, you can
+specify this location in the build file.</p>
+
+<h3 id="projectModules">Projects and modules</h3>
+
+<p>A <em>project</em> in Android Studio represents a complete Android app. Android Studio
+projects consist of one or more modules. A <em>module</em> is a component of your app that you can
+build, test, or debug independently. Modules contain the source code and resources for your app.
+Android Studio projects contain three kinds of modules:</p>
+
+<ul>
+ <li><em>Java library modules</em> contain reusable code. The build system generates a
+ JAR package for Java library modules.</li>
+ <li><em>Android library modules</em> contain reusable Android-specific code and resources.
+ The build system generates an AAR (Android ARchive) package for library modules.</li>
+ <li><em>Android application modules</em> contain application code and may depend on library
+ modules, although many Android apps consists of only one application module. The build
+ system generates an APK package for application modules.</li>
+</ul>
+
+<p>Android Studio projects contain a top-level Gradle build file that lists all the modules in
+the project, and each module contains its own Gradle build file.</p>
+
+<h3 id="dependencies">Dependencies</h3>
+
+<p>The Android Studio build system manages project dependencies and supports module dependencies,
+local binary dependencies, and remote binary dependencies.</p>
+
+<dl>
+ <dt><em>Module Dependencies</em></dt>
+ <dd><p>A project module can include in its build file a list of other modules it depends on.
+ When you build this module, the build system assembles and includes the required
+ modules.</p></dd>
+ <dt><em>Local Dependencies</em></dt>
+ <dd><p>If you have binary archives in your local filesystem that a module depends on, such as
+ JAR files, you can declare these dependencies in the build file for that
+ module.</p></dd>
+ <dt><em>Remote Dependencies</em></dt>
+ <dd><p>When some of your dependencies are available in a remote repository, you do not have
+ to download them and copy them into your project. The Android Studio build system supports
+ remote <em>Maven</em> dependencies. <a href="http://maven.apache.org/">Maven</a> is a
+ popular software project management tool that helps organize project dependencies using
+ repositories.</p>
+ <p>Many popular software libraries and tools are available in public Maven repositories.
+ For these dependencies you only have to specify their Maven coordinates, which uniquely
+ identify each element in a remote repository. The format for Maven coordinates used in the
+ build system is <code>group:name:version</code>. For example, the Maven coordinates for
+ version 16.0.1 of the Google Guava libraries are
+ <code>com.google.guava:guava:16.0.1</code>.</p>
+ <p>The <a href="http://search.maven.org">Maven Central Repository</a> is widely used to
+ distribute many libraries and tools.</p>
+ </dd>
+</dl>
+
+<h3 id="buildTasks">Build tasks</h3>
+
+<p>The Android Studio build system defines a hierarchical set of build tasks: the top-level
+tasks invoke the tasks they depend on to produce the necessary outcomes. The build system
+provides project tasks to build your app and module tasks to build modules independently.</p>
+
+<p>You can view the list of available tasks and invoke any task from Android Studio and from
+the command line, as described in
+<a href="#buildProject">Build the project in Android Studio</a> and and
+<a href="#buildCmd">Build the project from the command line</a>.</p>
+
+<h3 id="gradleWrapper">The Gradle wrapper</h3>
+
+<p>Android Studio projects contain the <em>Gradle wrapper</em>, which consists of:</p>
+
+<ul>
+ <li>A JAR file</li>
+ <li>A properties file</li>
+ <li>A shell script for Windows platforms</li>
+ <li>A shell script for Mac and Linux platforms</li>
+</ul>
+
+<p class="note"><strong>Note:</strong> You should submit all of these files to your source
+control system.</p>
+
+<p>Using the Gradle wrapper (instead of the local Gradle installation) ensures that
+you always run the version of Gradle defined in the properties file. To configure your project
+to use a newer version of Gradle, edit the properties file and specify the new version there.
+
+<p>Android Studio reads the properties file from the Gradle wrapper directory inside your project
+and runs the wrapper from this directory, so you can seamlessly work with multiple projects
+that require different versions of Gradle.</p>
+
+<p class="note"><strong>Note:</strong> Android Studio does not use the shell scripts, so any
+changes you make to them won't work when building from the IDE. You should define your custom
+logic inside Gradle build files instead.</p>
+
+<p>You can run the shell scripts to build your project from the command line on your development
+machine and on other machines where Android Studio is not installed.</p>
+
+
+<h2 id="creatingBuilding">Create and Build an Android Studio Project</h2>
+
+<p>This section builds on the concepts presented above and shows you how to:</p>
+
+<ul>
+ <li>Create projects and modules.</li>
+ <li>Work with the project structure.</li>
+ <li>Edit build files to configure the build process.</li>
+ <li>Build and run your app.</li>
+</ul>
+
+<h3 id="createProject">Create a project in Android Studio</h3>
+
+<p>To create a new project in Android Studio:</p>
+
+<ol>
+ <li>Click <strong>File</strong> and select <strong>New Project</strong>.</li>
+ <li>In the window that appears, enter "BuildSystemExample" in the <em>Application</em>
+ name field.</li>
+ <li>Leave the rest of the values unchanged and click <strong>Next</strong>.</li>
+ <li>Leave the default icon settings unchanged and click <strong>Next</strong>.</li>
+ <li>Select <em>Blank Activity</em> and click <strong>Next</strong>.</li>
+ <li>Leave the default activity and layout names unchanged and click
+ <strong>Finish</strong>.</li>
+</ol>
+
+<p>Figure 1 shows how the Android Studio window looks like after creating the project.</p>
+
+<img src="{@docRoot}images/tools/as-mainscreen.png" alt="" />
+<p class="img-caption"><strong>Figure 1.</strong> Previewing your app.</p>
+
+<h3 id="projectStructure">The project structure</h3>
+
+<p>Android Studio projects contain an application module by default (<code>app</code>).
+Table 1 lists where the main components of your app are located inside this module.</p>
+
+<p class="table-caption" id="table1">
+<strong>Table 1.</strong> Default location of the components in an application module.</p>
+<table>
+ <tr>
+ <th scope="col">Component</th>
+ <th scope="col">Location</th>
+ </tr>
+ <tr>
+ <td>Source files</td>
+ <td><code>app/src/main/java/<package>/</code></td>
+ </tr>
+ <tr>
+ <td>Resource files</td>
+ <td><code>app/src/main/res/</code></td>
+ </tr>
+ <tr>
+ <td>Manifest file</td>
+ <td><code>app/src/main/AndroidManifest.xml</code></td>
+ </tr>
+ <tr>
+ <td>Build file</td>
+ <td><code>app/build.gradle</code></td>
+ </tr>
+</table>
+
+<p>When you add additional modules to your project, the directory structure for each module is
+similar to the one shown in table 1, replacing <code>app</code> by the name of the module.</p>
+
+<h3 id="addLibModule">Add a library module</h3>
+
+<p>This section shows you how to add a library module to your project and how to add this
+library as a dependency of an application module.</p>
+
+<h4>Create a new library module</h4>
+
+<p>It is good development practice to group functionality that you may reuse in other apps inside
+a library module. To create a library module inside the <code>BuildSystemExample</code>
+project:</p>
+
+<ol>
+ <li>Click <strong>File</strong> and select <strong>New Module</strong>.</li>
+ <li>On the window that appears, select <strong>Android Library</strong> and click
+ <strong>Next</strong>.</li>
+ <li>Leave the default module name (<code>lib</code>) unchanged and click
+ <strong>Next</strong>.</li>
+ <li>Select <em>Blank Activity</em> and click <strong>Next</strong>.</li>
+ <li>Type "LibActivity1" on the <em>Activity Name</em> field and click
+ <strong>Finish</strong>.</li>
+</ol>
+
+<p>The project now contains two modules, <code>app</code> and <code>lib</code>, with one activity
+in each module.</p>
+
+<h4 id="openActFromLib">Open an activity from a library module</h4>
+
+<p>Library modules contain activities and other logic that one or more application modules reuse.
+In this example, <code>MainActivity</code> in the app module opens <code>LibActivity1</code>
+from the <code>lib</code> module. To open <code>LibActivity1</code> from
+<code>MainActivity</code>:</p>
+
+<ol>
+ <li>
+ <p>Edit the layout file for <code>MainActivity</code> in the <code>app</code> module.
+ This file is located in <code>app/src/main/res/layout/activity_main.xml</code>. Replace
+ the contents of this file with the following:</p>
+ <p><pre>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context="com.buildsystemexample.app.MainActivity">
+
+ <Button
+ android:id="@+id/button1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/button1"
+ android:onClick="onButton1Clicked"/>
+
+</LinearLayout>
+</pre></p>
+ </li>
+ <li>
+ In this layout file, click on the line that contains
+ <code>android:text="@string/button1"</code> and press <strong>Alt+Enter</strong>. Follow
+ the suggestion from Android Studio to add a string resource with the value
+ "Open LibActivity1".
+ </li>
+ <li>
+ In this layout file, click on the line that contains
+ <code>android:onClick="onButton1Clicked"</code> and press <strong>Alt+Enter</strong>.
+ Follow the suggestion from Android Studio to add the <code>onButton1Clicked</code>
+ method to <code>MainActivity</code>.
+ </li>
+ <li>
+ <p>Copy the following code inside the <code>onButton1Clicked</code> method in
+ <code>MainActivity</code>:</p>
+ <p><pre>
+public void onButton1Clicked(View view) {
+ Intent intent = new Intent(this, LibActivity1.class);
+ startActivity(intent);
+}</pre></p>
+ </li>
+ <li>
+ Click on <code>LibActivity1</code> in the first line inside the
+ <code>onButton1Clicked</code> method of <code>MainActivity</code> and press
+ <strong>Alt+Enter</strong>. Follow the suggestion from Android Studio to add an import
+ for <code>LibActivity1</code> from the lib module.
+ </li>
+</ol>
+
+<p>When the user taps the <strong>Open LibActivity1</strong> button on <code>MainActivity</code>
+(from the <code>app</code> module), <code>LibActivity1</code> (from the <code>lib</code> module)
+starts.</p>
+
+<h4>Add a dependency on a library module</h4>
+
+<p>The <code>app</code> module now depends on the <code>lib</code> module, but the build system
+does not know about this yet. Edit the build file for the <code>app</code> module (
+<code>app/build.gradle</code>) and add a dependency on the <code>lib</code> module:</p>
+
+<pre>
+...
+dependencies {
+ ...
+ compile project(":lib")
+}
+</pre>
+
+<p>The <code>lib</code> module can still be built and tested independently, and the build system
+creates an AAR package for it that you could reuse in other projects.</p>
+
+<h3 id="buildProject">Build the project in Android Studio</h3>
+
+<p>To build the project on Android Studio, click <strong>Build</strong> and select
+<strong>Make Project</strong>. The status bar at the bottom of the window shows the current
+progress of the build:</p>
+
+<p><code>Gradle: Executing tasks: [:app:assembleDebug, :lib:bundleDebug]</code></p>
+
+<p class="note">If your project uses product flavors, Android Studio invokes the task for the
+selected build variant. For more information, see <a href="#workBuildVariants">Work with build
+variants.</a></p>
+
+<p>Click <img src="{@docRoot}images/tools/as-gradlebutton.png" alt=""
+style="vertical-align:bottom;margin:0;"/> on the bottom
+right part of the window to show the <em>Gradle Console</em>, as shown in figure 2.</p>
+
+<img src="{@docRoot}images/tools/as-gradleconsole.png" alt="" />
+<p class="img-caption"><strong>Figure 2.</strong> The Gradle Console in Android Studio.</p>
+
+<p>The Gradle Console shows the build tasks and subtasks that the build system runs for
+Android Studio. If the build fails, you can find more details on the console. To hide the Gradle
+Console, click <img src="{@docRoot}images/tools/as-gradlebutton.png" alt=""
+style="vertical-align:bottom;margin:0;"/> again.</p>
+
+<p>To view the list of all available build tasks in Android Studio, click <strong>Gradle</strong>
+on the right side of the IDE window. The <em>Gradle tasks</em> panel appears as shown in
+figure 3. Double-click any build task to run it in Android Studio. To hide the <em>Gradle tasks</em>
+panel, click <strong>Gradle</strong> again.</p>
+
+<img src="{@docRoot}images/tools/as-gradlepanel.png" alt="" />
+<p class="img-caption"><strong>Figure 3.</strong> The list of build tasks in Android Studio.</p>
+
+
+<h3 id="buildCmd">Build the project from the command line</h3>
+
+<p>To build the project from the command line, open a terminal window and navigate to the project
+root. On Windows platforms, type this command:</p>
+
+<pre>
+> gradlew.bat assembleDebug
+</pre>
+
+<p>On Mac OS and Linux platforms, type these commands:</p>
+
+<pre>
+$ chmod +x gradlew
+$ ./gradlew assembleDebug
+</pre>
+
+<p>The first command (<code>chmod</code>) adds the execution permission to the Gradle wrapper
+script and is only necessary the first time you build this project from the command line.</p>
+
+<p>The output of <code>gradlew</code> is similar to the output in the Gradle Console from
+figure 2.</p>
+
+<p>The <code>assembleDebug</code> build task builds the debug version of your app and signs it
+with the default local certificate, so that you can install it on the emulator and on real devices
+for debugging purposes.</p>
+
+<p>After you build the project, the output APK for the app module is located in
+<code>app/build/apk/</code>, and the output AAR for the lib module is located in
+<code>lib/build/libs/</code>.</p>
+
+<p>To see a list of all available build tasks for your project, type this command:</p>
+
+<pre>
+$ ./gradlew tasks
+</pre>
+
+
+<h2 id="configBuild">Configure the Build</h2>
+
+<p>This section uses the <code>BuildSystemExample</code> project from the previous section and
+shows you how to:</p>
+
+<ul>
+ <li>Use the syntax from the Android plugin for Gradle in build files.</li>
+ <li>Declare dependencies.</li>
+ <li>Configure ProGuard settings.</li>
+ <li>Configure signing settings.</li>
+ <li>Work with build variants.</li>
+</ul>
+
+<h3 id="buildFileBasics">Build file basics</h3>
+
+<p>Android Studio projects contain a top-level build file and a build file for each module. The
+build files are called <code>build.gradle</code>, and they are plain text files that use
+<a href="http://groovy.codehaus.org">Groovy</a> syntax to configure the build with the elements
+provided by the Android plugin for Gradle. In most cases, you only need to edit the build files
+at the module level. For example, the build file for the app module in the
+<code>BuildSystemExample</code> project looks like this:</p>
+
+<pre>
+apply plugin: 'android'
+
+android {
+ compileSdkVersion 19
+ buildToolsVersion "19.0.0"
+
+ defaultConfig {
+ minSdkVersion 8
+ targetSdkVersion 19
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ runProguard true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), \
+ 'proguard-rules.txt'
+ }
+ }
+}
+
+dependencies {
+ compile project(":lib")
+ compile 'com.android.support:appcompat-v7:19.0.1'
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+}
+</pre>
+
+<p><code>apply plugin: 'android'</code> applies the Android plugin for Gradle to this build.
+This adds Android-specific build tasks to the top-level build tasks and makes the
+<code>android {...}</code> element available to specify Android-specific build options.</p>
+
+<p><code>android {...}</code> configures all the Android-specific build options:</p>
+
+<ul>
+ <li>The <code>compileSdkVersion</code> property specifies the compilation target.</li>
+ <li><p>The <code>buildToolsVersion</code> property specifies what version of the build tools
+ to use. To install several versions of the build tools, use the SDK Manager.</p>
+ <p class="note"><strong>Note:</strong> Always use a build tools version whose major
+ revision number is higher or equal to that of your compilation target and target SDK.</p>
+ </li>
+ <li><p>The <code>defaultConfig</code> element configures core settings and
+ entries in the manifest file (<code>AndroidManifest.xml</code>) dynamically from the
+ build system. The values in <code>defaultConfig</code> override those in the manifest
+ file.</p>
+ <p>The configuration specified in the <code>defaultConfig</code> element applies
+ to all build variants, unless the configuration for a build variant overrides some
+ of these values.</p>
+ </li>
+ <li>The <code>buildTypes</code> element controls how to build and package your app.
+ By default, the build system defines two build types: <em>debug</em> and
+ <em>release</em>. The debug build type includes debugging symbols and is signed with
+ the debug key. The release build type is not signed by default.
+ In this example the build file configures the release version to use
+ ProGuard.</li>
+</ul>
+
+<p>The <code>dependencies</code> element is outside and after the <code>android</code> element.
+This element declares the dependencies for this module. Dependencies are covered in the following
+sections.</p>
+
+<p class="note"><strong>Note:</strong> When you make changes to the build files in your project,
+Android Studio requires a project sync to import the build configuration changes. Click
+<strong>Sync Now</strong> on the yellow notification bar that appears for Android Studio
+to import the changes.</p>
+
+<img src="{@docRoot}images/tools/as-gradlesync.png" alt="" />
+<p class="img-caption"><strong>Figure 4.</strong> Sync the project in Android Studio.</p>
+
+<h3 id="declareDeps">Declare dependencies</h3>
+
+<p>The <code>app</code> module in <code>BuildSystemExample</code> declares three
+dependencies:</p>
+
+<pre>
+...
+dependencies {
+ // Module dependency
+ compile project(":lib")
+
+ // Remote binary dependency
+ compile 'com.android.support:appcompat-v7:19.0.1'
+
+ // Local binary dependency
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+}
+</pre>
+
+<p>Each of these dependencies is described below. The build system adds all the
+<code>compile</code> dependencies to the compilation classpath and includes them in the final
+package.</p>
+
+<h4>Module dependencies</h4>
+
+<p>The <code>app</code> module depends on the <code>lib</code> module, because
+<code>MainActivity</code> launches <code>LibActivity1</code> as described in
+<a href="#openActFromLib">Open an Activity from a Library Module</a>.</p>
+
+<p><code>compile project(":lib")</code> declares a dependency on the <code>lib</code>
+module of <code>BuildSystemExample</code>. When you build the <code>app</code> module,
+the build system assembles and includes the <code>lib</code> module.</p>
+
+<h4>Remote binary dependencies</h4>
+
+<p>The <code>app</code> and <code>lib</code> modules both use the <code>ActionBarActivity</code>
+class from the Android Support Library, so these modules depend on it.</p>
+
+<p><code>compile 'com.android.support:appcompat-v7:19.0.1'</code> declares a dependency on
+version 19.0.1 of the Android Support Library by specifying its Maven coordinates. The Android Support
+Library is available in the <em>Android Repository</em> package of the Android SDK. If your
+SDK installation does not have this package, download and install it using the SDK Manager.</p>
+
+Android Studio configures
+projects to use the Maven Central Repository by default. (This configuration is included in the
+top-level build file for the project.)</p>
+
+<h4>Local binary dependencies</h4>
+
+<p>The modules in <code>BuildSystemExample</code> do not use any binary dependencies from the
+local file system. If you have modules that require local binary dependencies, copy the JAR
+files for these dependencies into <code><moduleName>/libs</code> inside your project.</p>
+
+<p><code>compile fileTree(dir: 'libs', include: ['*.jar'])</code> tells the build system that any
+JAR file inside <code>app/libs</code> is a dependency and should be included in the compilation
+classpath and in the final package.</p>
+
+<p>For more information about dependencies in Gradle, see
+<a href="http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html">Dependency
+Management Basics</a> in the Gradle User Guide.</p>
+
+<h3 id="runProguard">Run ProGuard</h3>
+
+<p>The build system can run
+<a href="http://developer.android.com/tools/help/proguard.html">ProGuard</a> to obfuscate your
+classes during the build process. In <code>BuildSystemExample</code>, modify the build file for
+the app module to run ProGuard for the release build:</p>
+
+<pre>
+...
+android {
+ ...
+ buildTypes {
+ release {
+ runProguard true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), \
+ 'proguard-rules.txt'
+ }
+ }
+}
+...
+</pre>
+
+<p><code>getDefaultProguardFile('proguard-android.txt')</code> obtains the default ProGuard
+settings from the Android SDK installation. Android Studio adds the module-specific rules file
+<code>proguard-rules.txt</code> at the root of the module, where you can add custom ProGuard
+rules.</p>
+
+<p>You can build the release version of your application from the command line or using Android
+Studio. To build it from the command line, invoke the <code>assembleRelease</code> build task using
+the Gradle wrapper script (<code>gradlew assembleRelease</code>). To build it from Android
+Studio:</p>
+
+<ol>
+ <li>Click <strong>Gradle</strong> on the right side of the IDE window.</li>
+ <li>On the <em>All tasks</em> section of the sidebar that appears, expand
+ <strong>BuildSystemExample</strong>.</li>
+ <li>Expand <strong>:app</strong> and double-click <strong>assembleRelease</strong>.</li>
+</ol>
+
+<p>You can use this procedure to invoke any build task from Android Studio.</p>
+
+<h3 id="configureSigning">Configure signing settings</h3>
+
+<p>The debug and the release versions of the app differ on whether the application can be
+debugged on secure devices and on how the APK is signed. The build system signs the debug
+version with a default key and certificate using known credentials to avoid a password prompt at
+build time. The build system does not sign the release version unless you explicitly define a
+signing configuration for this build.</p>
+
+<p>To sign the release version of <code>BuildSystemExample</code>:</p>
+
+<ol>
+ <li><p>Copy your release key to the root directory of the <code>app</code> module
+ (<code>app/</code>).</p>
+ <p>This ensures that the build system can find your key when you move the location of your
+ project or when you build the project on a different machine. If you do not have a release
+ key, you can generate one as described in
+ <a href="{@docRoot}tools/publishing/app-signing.html">Signing your Applications</a>.</p>
+ </li>
+ <li><p>Add the signing configuration to the build file for the <code>app</code> module:</p>
+ <p><pre>
+...
+android {
+ ...
+ defaultConfig { ... }
+ signingConfigs {
+ release {
+ storeFile file("myreleasekey.keystore")
+ storePassword "password"
+ keyAlias "MyReleaseKey"
+ keyPassword "password"
+ }
+ }
+ buildTypes {
+ release {
+ ...
+ signingConfig signingConfigs.release
+ }
+ }
+}
+...
+</pre></p>
+ </li>
+ <li>Invoke the <code>assembleRelease</code> build task from Android Studio or from the command
+ line.</li>
+</ol>
+
+<p>The package in <code>app/build/apk/app-release.apk</code> is now signed with your release key.</p>
+
+<p class="note"><strong>Note:</strong> Including the passwords for your release key and keystore
+inside the build file is not a good security practice. Alternatively, you can configure the build
+file to obtain these passwords from environment variables or have the build process prompt you
+for these passwords.</p>
+
+<p>To obtain these passwords from environment variables:</p>
+
+<pre>
+storePassword System.getenv("KSTOREPWD")
+keyPassword System.getenv("KEYPWD")
+</pre>
+
+<p>To have the build process prompt you for these passwords if you are invoking the build from
+the command line:</p>
+
+<pre>
+storePassword System.console().readLine("\nKeystore password: ")
+keyPassword System.console().readLIne("\nKey password: ")
+</pre>
+
+<h3 id="workBuildVariants">Work with build variants</h3>
+
+<p>This section describes how the build system can help you create different versions of the same
+application from a single project. This is useful when you have a demo version and a paid version
+of your app, or if you want to distribute multiple APKs for different device configurations on
+Google Play.</p>
+
+<p>The build system uses <em>product flavors</em> to create different versions of your app. Each
+version of your app can have different features or device requirements. The build system generates
+a different APK for each version of your app.</p>
+
+<h4>Build variants</h4>
+
+<p>Each version of your app is represented in the build system by a <em>build variant</em>.
+Build variants are combinations of build types and product flavor configurations. Android Studio
+projects define two build types (<em>debug</em> and <em>release</em>) and no product flavors by
+default. These projects consists of two build variants, debug and release, and the build system
+generates an APK for each.</p>
+
+<p>The exercise in this section defines two product flavors, <em>demo</em> and <em>full</em>.
+This generates four build variants:</p>
+
+<ul>
+ <li>demo-debug</li>
+ <li>demo-release</li>
+ <li>full-debug</li>
+ <li>full-release</li>
+</ul>
+
+<p>In this case the build system creates four APKs, one for each of these build variants.</p>
+
+<p>Some projects have complex combinations of features along more than one dimension, but they
+still represent the same app. For example, in addition to having a demo and a full version of the
+app, some games may contain binaries specific to a particular CPU/ABI. The flexibility of
+the build system makes it possible to generate the following build variants for such a project:</p>
+
+<ul>
+ <li>x86-demo-debug</li>
+ <li>x86-demo-release</li>
+ <li>x86-full-debug</li>
+ <li>x86-full-release</li>
+ <li>arm-demo-debug</li>
+ <li>arm-demo-release</li>
+ <li>arm-full-debug</li>
+ <li>arm-full-release</li>
+ <li>mips-demo-debug</li>
+ <li>mips-demo-release</li>
+ <li>mips-full-debug</li>
+ <li>mips-full-release</li>
+</ul>
+
+<p>This project would consist of two build types (<em>debug</em> and <em>release</em>)
+and two <em>dimensions</em> of product flavors, one for app type (demo or full) and one for
+CPU/ABI (x86, ARM, or MIPS). For more information on flavor dimensions, see the
+<a href="http://tools.android.com/tech-docs/new-build-system/user-guide">Gradle Plugin User
+Guide</a>.</p>
+
+<h4>Source directories</h4>
+
+<p>To build each version of your app, the build system combines source code and
+resources from:</p>
+
+<ul>
+ <li><code>src/main/</code> - the main source directory (common to all variants)</li>
+ <li><code>src/<buildType>/</code> - the build type source directory</li>
+ <li><code>src/<flavorName>/</code> - the flavor source directory</li>
+</ul>
+
+<p>The number of flavor source directories used in the build depends on the flavor configuration
+of your project:</p>
+<ul>
+ <li><p>For projects that do not define any flavors, the build system does not use any
+ flavor source directories. For example, to generate the <em>release</em> build variant
+ in projects with no flavors, the build system uses:</p>
+ <ul>
+ <li><code>src/main/</code></li>
+ <li><code>src/release/</code> (build type)</li>
+ </ul>
+ </li>
+ <li><p>For projects that define a set of flavors, the build system uses one flavor source
+ directory. For example, to generate the <em>full-debug</em> build variant in the example
+ in this section, the build system uses:</p>
+ <ul>
+ <li><code>src/main/</code></li>
+ <li><code>src/debug/</code> (build type)</li>
+ <li><code>src/full/</code> (flavor)</li>
+ </ul>
+ </li>
+ <li><p>For projects that use flavor dimensions, the build system uses one flavor source
+ directory per dimension. For example, to generate the <em>arm-demo-release</em> build
+ variant in the previous example, the build system uses:</p>
+ <ul>
+ <li><code>src/main/</code></li>
+ <li><code>src/release/</code> (build type)</li>
+ <li><code>src/demo/</code> (flavor - app type dimension)</li>
+ <li><code>src/arm/</code> (flavor - ABI dimension)</li>
+ </ul>
+ </li>
+</ul>
+
+<p class="note"><strong>Note:</strong> The build type and flavor source directories are optional,
+and Android Studio does not create these directories for you. The build system does not use them
+if they are not present.</p>
+
+<p>The source code from these directories is used together to generate the output for a build
+variant. You can have classes with the same name in different directories as long as those
+directories are not used together in the same variant. The exercise in this section shows you
+how to create different versions of the same activity class in different variants.</p>
+
+<p>The build system merges all the manifests into a single manifest, so each build variant
+can define different components or permissions in the final manifest.</p>
+
+<p>The build system merges all the resources from the all the source directories. If different
+folders contain resources with the same name for a build variant, the priority order is the
+following: build type resources override those from the product flavor, which override the
+resources in the main source directory.</p>
+
+<p class="note"><strong>Note:</strong> Build variants enable you to reuse common activities,
+application logic, and resources across different versions of your app.</p>
+
+<h4>Product flavors in BuildSystemExample</h4>
+
+<p>To create different versions of your app:</p>
+
+<ol>
+ <li>Define product flavors in the build file.</li>
+ <li>Create additional source directories for each flavor.</li>
+ <li>Add the flavor-specific sources to your project.</li>
+</ol>
+
+<p>The rest of this section walks you through these steps in detail using the
+<code>BuildSystemExample</code> project. You create two flavors of the
+<code>BuildSystemExample</code> app, a demo flavor and a full flavor. Both flavors share
+<code>MainActivity</code>, to which you add a new button to launch a new activity,
+<code>SecondActivity</code>. This new activity is different for each flavor, so you simulate a
+situation where the new activity would have more features in the full flavor than in the demo
+flavor. At the end of the exercise, you end up with two different APKs, one for each flavor.</p>
+
+<h4>Define product flavors in the build file</h4>
+
+<p>To define two product flavors, edit the build file for the app module to add the following
+configuration:</p>
+
+<pre>
+...
+android {
+ ...
+ defaultConfig { ... }
+ signingConfigs { ... }
+ buildTypes { ... }
+ productFlavors {
+ demo {
+ packageName "com.buildsystemexample.app.demo"
+ versionName "1.0-demo"
+ }
+ full {
+ packageName "com.buildsystemexample.app.full"
+ versionName "1.0-full"
+ }
+ }
+}
+...
+</pre>
+
+<p>The product flavor definitions support the same properties as the <code>defaultConfig</code>
+element. The base configuration for all flavors is specified in <code>defaultConfig</code>, and each
+flavor can override any value. The build file above assigns a different package name to each flavor:
+since each flavor definition creates a different app, they each need a distinct package name.</p>
+
+<p class="note"><strong>Note:</strong> To distribute your app using
+<a href="{@docRoot}google/play/publishing/multiple-apks.html">Multiple APK Support</a> in
+Google Play, assign the same package name to all variants and give each variant a different
+<code>versionCode</code>. To distribute different variants of your app as separate apps in Google
+Play, assign a different package name to each variant.</p>
+
+<h4>Add additional source directories for each flavor</h4>
+
+<p>Now you create source folders and add a <code>SecondActivity</code> to each flavor. To create
+the source directory structure for the demo flavor:</p>
+
+<ol>
+ <li>On the <em>Project</em> panel, expand <strong>BuildSystemExample</strong>, and then expand
+ the <strong>app</strong> directory.</li>
+ <li>Right click the <strong>src</strong> directory under <em>app</em> and select
+ <strong>New</strong> > <strong>Directory</strong>.</li>
+ <li>Enter "demo" as the name of the new directory and click <strong>OK</strong>.</li>
+ <li><p>Similarly, create the following directories:</p>
+ <ul>
+ <li><code>app/src/demo/java</code></li>
+ <li><code>app/src/demo/res</code></li>
+ <li><code>app/src/demo/res/layout</code></li>
+ <li><code>app/src/demo/res/values</code></li>
+ </ul>
+ </li>
+</ol>
+
+<p>The resulting directory structure looks like figure 5.</p>
+
+<img src="{@docRoot}images/tools/as-demoflavordirs.png" alt="" />
+<p class="img-caption"><strong>Figure 5.</strong> New source directories for the demo flavor.</p>
+
+<h4>Add a new activity to each flavor</h4>
+
+<p>To add <code>SecondActivity</code> to the <code>demo</code> flavor:</p>
+
+<ol>
+ <li>On the <em>Project</em> panel, right click on the <strong>app</strong> module and select
+ <strong>New</strong> > <strong>Activity</strong>.</li>
+ <li>Select <strong>Blank Activity</strong> and click <strong>Next</strong>.</li>
+ <li>Enter "SecondActivity" as the activity name.</li>
+ <li>Enter "com.buildsystemexample.app" as the package name and click
+ <strong>Finish</strong>.</li>
+ <li>Right click on the <strong>java</strong> directory under <em>app/src/demo</em> and select
+ <strong>New</strong> > <strong>Package</strong>.</li>
+ <li>Enter "com.buildsystemexample.app" as the package name and click <strong>OK</strong>.</li>
+ <li>Drag <strong>SecondActivity</strong> and drop it under the new package in
+ <em>app/src/demo/java</em>.</li>
+ <li>Accept the default values and click <strong>Refactor</strong>.</li>
+</ol>
+
+<p>To add the layout for <code>SecondActivity</code> and a strings resource to the demo flavor:</p>
+
+<ol>
+ <li>Drag <strong>activity_second.xml</strong> from <em>app/src/main/res/layout</em> and drop it
+ inside <em>app/src/demo/res/layout</em>.</li>
+ <li>Accept the default values on the window that appears and click <code>OK</code>.</li>
+ <li>Copy <strong>strings.xml</strong> from <em>app/src/main/res</em> into
+ <em>app/src/demo/res</em>.</li>
+ <li><p>Replace the contents of the new copy of <code>strings.xml</code> with the
+ following:</p>
+ <p><pre>
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="hello_world">Demo version only.</string>
+</resources>
+</pre></p>
+ </li>
+</ol>
+
+<p>Now you add source folders and <code>SecondActivity</code> to the full flavor by making a copy
+of the <code>demo</code> flavor:</p>
+
+<ol>
+ <li>On the <em>Project</em> panel, right click on the <strong>demo</strong> directory under
+ <em>app/src</em> and select <strong>Copy</strong>.</li>
+ <li>Right-click on the <strong>src/</strong> directory under <em>app/</em> and select
+ <strong>Paste</strong>.</li>
+ <li>On the window that appears, enter "full" as the new name and click <strong>OK</strong>.</li>
+ <li><p>Replace the contents of <strong>strings.xml</strong> under <em>src/full/res/values</em>
+ with the following:</p>
+ <p><pre>
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="hello_world">This is the full version!</string>
+</resources>
+</pre></p>
+ </li>
+</ol>
+
+<p class="note"><strong>Note:</strong> From this point on, you could develop
+<code>SecondActivity</code> independently inside each
+flavor. You can add more features to this activity in the <code>full</code> flavor.</p>
+
+<p>To work on files from a particular flavor, click on <strong>Build Variants</strong> on the left
+of the IDE window and select the flavor you want to modify in the <em>Build Variants</em> panel,
+as shown in figure 5. Android Studio may show errors in source files from flavors other than the
+one selected in the <em>Build Variants</em> panel, but this does not affect the outcome of the
+build.</p>
+
+<img src="{@docRoot}images/tools/as-buildvariants.png" alt="" />
+<p class="img-caption"><strong>Figure 6.</strong> The Build Variants panel.</p>
+
+<h4>Launch a flavor-specific activity from the main activity</h4>
+
+<p>Since the flavor-specific activity (<code>SecondActivity</code>) has the same package name and
+activity name in both flavors, you can launch it from the main activity, which is common to all
+flavors. To modify the main activity:</p>
+
+<ol>
+ <li><p>Edit <code>activity_main.xml</code> and add a new button to
+ <code>MainActivity</code>:</p>
+ <p><pre>
+<LinearLayout ...>
+ ...
+ <Button
+ android:id="@+id/button2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/button2"
+ android:onClick="onButton2Clicked"/>
+</LinearLayout>
+</pre></p>
+ </li>
+ <li>Click on the areas marked in red in the layout file and press <strong>Alt</strong>+
+ <strong>Enter</strong>. Follow the suggestions from Android Studio to add a new string
+ resource with value “Open Second Activity” and an <code>onButton2Clicked</code> method to
+ <code>MainActivity</code>.</li>
+ <li><p>Add the following code to the <code>onButton2Clicked</code> method of
+ <code>MainActivity</code>:</p>
+ <p><pre>
+public void onButton2Clicked(View view) {
+ Intent intent = new Intent(this, SecondActivity.class);
+ startActivity(intent);
+}
+</pre></p>
+ </li>
+ <li><p>Edit the app's manifest to include a reference to <code>SecondActivity</code>:</p>
+ <p><pre>
+<manifest ...>
+ <application ...>
+ ...
+ <activity
+ android:name="com.buildsystemexample.app.SecondActivity"
+ android:label="@string/title_activity_second" >
+ </activity>
+ </application>
+</manifest>
+</pre></p>
+ </li>
+</ol>
+
+<h4>Build output</h4>
+
+<p>The <code>BuildSystemExample</code> app is now complete. To build it, invoke the
+<code>assemble</code> task from Android Studio or from the command line.</p>
+
+<p>The build generates an APK for each build variant:
+the <code>app/build/apk/</code> directory contains packages named
+<code>app-<flavor>-<buildtype>.apk</code>; for example, <code>app-full-release.apk</code> and
+<code>app-demo-debug.apk</code>.</p>
+
+
+<h2 id="reference">Reference</h2>
+
+<p>The build system is very flexible and has more features than those described here. For a
+complete reference, see the
+<a href="http://tools.android.com/tech-docs/new-build-system/user-guide">Android Plugin for Gradle
+User Guide</a>.</p>
diff --git a/docs/html/sdk/installing/studio.jd b/docs/html/sdk/installing/studio.jd
index feb7a6e..071492d 100644
--- a/docs/html/sdk/installing/studio.jd
+++ b/docs/html/sdk/installing/studio.jd
@@ -253,36 +253,36 @@
<td>Windows</td>
<td>
<a onclick="return onDownload(this)" id="win-studio"
- href="http://dl.google.com/android/studio/install/0.4.2/android-studio-bundle-133.970939-windows.exe">
- android-studio-bundle-133.970939-windows.exe
+ href="http://dl.google.com/android/studio/install/0.4.6/android-studio-bundle-133.1028713-windows.exe">
+ android-studio-bundle-133.1028713-windows.exe
</a>
</td>
- <td>515261701 bytes</td>
- <td>1e1ae28b1c00f43d55f17ee35bd4f5d2</td>
+ <td>519592042 bytes</td>
+ <td>9029c18738a75830786326d62c96d557</td>
</tr>
<tr>
<td><nobr>Mac OS X</nobr></td>
<td>
<a onclick="return onDownload(this)" id="mac-studio"
- href="http://dl.google.com/android/studio/install/0.4.2/android-studio-bundle-133.970939-mac.dmg">
- android-studio-bundle-133.970939-mac.dmg
+ href="http://dl.google.com/android/studio/install/0.4.6/android-studio-bundle-133.1028713-mac.dmg">
+ android-studio-bundle-133.1028713-mac.dmg
</a>
</td>
- <td>491773471 bytes</td>
- <td>6753f67c56acb17617bfbc5bc56384e7</td>
+ <td>497595811 bytes</td>
+ <td>eb2474e6d17537ddfa535e6fe8adcf0d</td>
</tr>
<tr>
<td>Linux</td>
<td>
<a onclick="return onDownload(this)" id="linux-studio"
- href="http://dl.google.com/android/studio/install/0.4.2/android-studio-bundle-133.970939-linux.tgz">
- android-studio-bundle-133.970939-linux.tgz
+ href="http://dl.google.com/android/studio/install/0.4.6/android-studio-bundle-133.1028713-linux.tgz">
+ android-studio-bundle-133.1028713-linux.tgz
</a>
</td>
- <td>516080363 bytes</td>
- <td>25455787d76e61baf34bf93eaa00ded6</td>
+ <td>522177460 bytes</td>
+ <td>cc847dd6249b3033737dabe0377c8c66</td>
</tr>
</table>
@@ -318,7 +318,7 @@
<h2 id="Installing">Installing Android Studio</h2>
-<p>Android Studio requires JDK 6 or greater (JRE alone is not sufficient). To check if you
+<p>Android Studio requires JDK 6 or greater (JRE alone is not sufficient). To check if you
have JDK installed (and which version), open a terminal and type <code>javac -version</code>.
If JDK is not available or the version is lower than 6,
<a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">download
@@ -430,6 +430,19 @@
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>Android Studio v0.4.6</a> <em>(March 2014)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+ <ul>
+ <li>See <a href="http://tools.android.com/recent">tools.android.com</a> for a full list of changes.</li>
+ </ul>
+ </div>
+</div>
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>Android Studio v0.4.2</a> <em>(Jan 2014)</em>
</p>
@@ -637,7 +650,7 @@
if (os) {
/* set up primary ACE download button */
$('#download-ide-button').show();
- $('#download-ide-button').append("Download Android Studio <span class='small'>v0.4.2</span>"
+ $('#download-ide-button').append("Download Android Studio <span class='small'>v0.4.6</span>"
+ "<br/> <span class='small'>for " + os + "</span>");
$('#download-ide-button').click(function() {return onDownload(this,true);}).attr('href', bundlename);
diff --git a/docs/html/tools/revisions/platforms.jd b/docs/html/tools/revisions/platforms.jd
index 99a271f..5d1d13b 100644
--- a/docs/html/tools/revisions/platforms.jd
+++ b/docs/html/tools/revisions/platforms.jd
@@ -93,6 +93,21 @@
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png"
+class="toggle-content-img" alt="" />Revision 4</a> <em>(March 2014)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <p>This release includes
+ <a href="{@docRoot}google/play-services/index.html">Google Play services</a> version 4.3,
+ allowing you to test your application in an emulator using the latest Google Play services.</p>
+
+ </div>
+</div>
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png"
class="toggle-content-img" alt="" />Revision 3</a> <em>(February 2014)</em>
</p>
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index a821757..d106f4a 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -57,6 +57,51 @@
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>ADT 22.6.2</a> <em>(March 2014)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+<dl>
+ <dt>Dependencies:</dt>
+
+ <dd>
+ <ul>
+ <li>Java 1.6 or higher is required.</li>
+ <li>Eclipse Indigo (Version 3.7.2) or higher is required.</li>
+ <li>This version of ADT is designed for use with
+ <a href="{@docRoot}tools/sdk/tools-notes.html">SDK Tools r22.6.2</a>.
+ If you haven't already installed SDK Tools r22.6.2 into your SDK, use the
+ Android SDK Manager to do so.</li>
+ </ul>
+ </dd>
+
+ <dt>General Notes:</dt>
+ <dd>
+ <ul>
+ <li><p>Changed the URL for the Android Developer Tools update site to require HTTPS.</p>
+ <p class="note"><strong>Note:</strong> If you are
+ <a href="{@docRoot}sdk/installing/installing-adt.html">updating ADT</a>, make sure
+ you use HTTPS in the URL for the Android Developer Tools update site.</p>
+ </li>
+ <li>Fixed a problem where Eclipse was non-responsive for a few seconds after opening
+ an XML file. (<a href="http://b.android.com/67084">Issue 67084</a>)</li>
+ <li>Fixed a problem where the SDK Manager threw a <code>NullPointerException</code> after
+ removing a virtual device that was created using the Android Wear
+ system image. (<a href="http://b.android.com/67588">Issue 67588</a>)</li>
+ <li>Fixed a problem where the layout preview for large screens in Eclipse showed the
+ resources from the <code>drawable-*</code> directories instead of those from the
+ <code>drawable-large-*</code> directories.</li>
+ <li>Fixed a problem with Nexus 5 Android virtual devices created from the command line
+ where the SD card file system was read-only.</li>
+ </ul>
+ </dd>
+</dl>
+</div>
+</div>
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>ADT 22.6.1</a> <em>(March 2014)</em>
</p>
@@ -78,8 +123,8 @@
<dt>General Notes:</dt>
<dd>
<ul>
- <li>Fixed a problem where the Android Virtual Device Manager could not create new virtual
- devices. (<a href="http://b.android.com/66661">Issue 66661</a>)</li>
+ <li>Fixed a problem where the Android Virtual Device Manager could not create new
+ virtual devices. (<a href="http://b.android.com/66661">Issue 66661</a>)</li>
<li><p>Fixed a problem with virtual devices created using ADT 22.3 or earlier.</p>
<p>If you created an Android Virtual Device using ADT 22.3 or earlier, the
AVD may be listed as <em>broken</em> in the AVD Manager in 22.6.1. To fix
@@ -102,7 +147,6 @@
</div>
</div>
-
<div class="toggle-content closed">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index 675cde3..14b5505 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -28,6 +28,41 @@
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>SDK Tools, Revision 22.6.2</a> <em>(March 2014)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <dl>
+ <dt>Dependencies:</dt>
+
+ <dd>
+ <ul>
+ <li>Android SDK Platform-tools revision 18 or later.</li>
+ <li>If you are developing in Eclipse with ADT, note that this version of SDK Tools is
+ designed for use with ADT 22.6.2 and later. If you haven't already, update your
+ <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> to 22.6.2.</li>
+ <li>If you are developing outside Eclipse, you must have
+ <a href="http://ant.apache.org/">Apache Ant</a> 1.8 or later.</li>
+ </ul>
+ </dd>
+
+ <dt>General Notes:</dt>
+ <dd>
+ <ul>
+ <li>Fixed a problem where the SDK Manager threw a <code>NullPointerException</code> after
+ removing a virtual device that was created using the Android Wear
+ system image. (<a href="http://b.android.com/67588">Issue 67588</a>)</li>
+ <li>Fixed a problem with Nexus 5 Android virtual devices created from the command line
+ where the SD card file system was read-only.</li>
+ </ul>
+ </dd>
+ </div>
+</div>
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>SDK Tools, Revision 22.6.1</a> <em>(March 2014)</em>
</p>
@@ -124,7 +159,7 @@
</ul>
</li>
<li>Check that production builds do not use mock location providers.</li>
- <li>Look for manifest values that are overwritten by values from Gradle build
+ <li>Look for manifest values that are overwritten by values from Gradle build
scripts.</li>
</ul>
</li>
@@ -148,7 +183,7 @@
(<a href="http://b.android.com/34233">Issue 34233</a>)</li>
</ul>
</li>
- <li>Fixed an issue with RenderScript support. Using RenderScript support mode
+ <li>Fixed an issue with RenderScript support. Using RenderScript support mode
now requires version 19.0.3 of the Build Tools.</li>
</ul>
</dd>
diff --git a/docs/html/tools/support-library/index.jd b/docs/html/tools/support-library/index.jd
index 389238f..e905285 100644
--- a/docs/html/tools/support-library/index.jd
+++ b/docs/html/tools/support-library/index.jd
@@ -58,10 +58,36 @@
<p>This section provides details about the Support Library package releases.</p>
-
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img" alt=""
+/>Android Support Library, revision 19.1.0</a> <em>(March 2014)</em>
+ </p>
+ <div class="toggle-content-toggleme">
+ <dl>
+ <dt>Changes for v4 support library:</dt>
+ <dd>
+ <ul>
+ <li>Added the {@link android.support.v4.widget.SwipeRefreshLayout} class,
+ which enables users to refresh the contents of a view with a vertical
+ swipe gesture.</li>
+ <li>Fixed accessibility issues with navigation drawers.</li>
+ </ul>
+ </dd>
+
+ <dt>Changes for v7 appcompat library:</dt>
+ <dd>
+ <ul>
+ <li>Fixed background issues with the action bar.</li>
+ </ul>
+ </dd>
+ </dl>
+ </div>
+</div>
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img" alt=""
/>Android Support Library, revision 19.0.1</a> <em>(December 2013)</em>
</p>
<div class="toggle-content-toggleme">
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index 382165c..c281644 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -36,6 +36,8 @@
Tips and Tricks</a></li>
<li><a href="<?cs var:toroot ?>sdk/installing/studio-layout.html">
Using the Layout Editor</a></li>
+ <li><a href="<?cs var:toroot ?>sdk/installing/studio-build.html">
+ Building Your Project with Gradle</a></li>
</ul>
</li>
<li><a href="<?cs var:toroot ?>sdk/exploring.html">
diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd
index 50485db..c4cb362 100644
--- a/docs/html/training/basics/firstapp/creating-project.jd
+++ b/docs/html/training/basics/firstapp/creating-project.jd
@@ -10,9 +10,9 @@
<!-- This is the training bar -->
-<div id="tb-wrapper">
-<div id="tb">
-
+<div id="tb-wrapper">
+<div id="tb">
+
<h2>This lesson teaches you to</h2>
<ol>
@@ -27,10 +27,10 @@
SDK</a></li>
<li><a href="{@docRoot}tools/projects/index.html">Managing Projects</a></li>
</ul>
-
-
-</div>
-</div>
+
+
+</div>
+</div>
<p>An Android project contains all the files that comprise the source code for your Android
app. The Android SDK tools make it easy to start a new Android project with a set of
@@ -42,7 +42,7 @@
<p class="note"><strong>Note:</strong> You should already have the Android SDK installed, and if
you're using Eclipse, you should also have the <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT
-plugin</a> installed (version 21.0.0 or higher). If you don't have these, follow the guide to <a
+plugin</a> installed (version 22.6.2 or higher). If you don't have these, follow the guide to <a
href="{@docRoot}sdk/installing/index.html">Installing the Android SDK</a> before you start this
lesson.</p>
@@ -50,7 +50,7 @@
<h2 id="Eclipse">Create a Project with Eclipse</h2>
<ol>
- <li>Click <strong>New</strong> <img src="{@docRoot}images/tools/eclipse-new.png"
+ <li>Click <strong>New</strong> <img src="{@docRoot}images/tools/eclipse-new.png"
style="vertical-align:baseline;margin:0" /> in the toolbar.</li>
<li>In the window that appears, open the <strong>Android</strong> folder,
select <strong>Android Application Project</strong>, and click <strong>Next</strong>.</li>
@@ -116,11 +116,11 @@
<li>Now you can select an activity template from which to begin building your app.
<p>For this project, select <strong>BlankActivity</strong> and click <strong>Next</strong>.</p>
</li>
- <li>Leave all the details for the activity in their default state and click
+ <li>Leave all the details for the activity in their default state and click
<strong>Finish</strong>.</li>
</ol>
-<p>Your Android project is now a basic "Hello World" app that contains some default files.
+<p>Your Android project is now a basic "Hello World" app that contains some default files.
To run the app, continue to the <a href="running-app.html">next lesson</a>.</p>
@@ -155,7 +155,7 @@
projects.</p></li>
</ol>
-<p>Your Android project is now a basic "Hello World" app that contains some default files.
+<p>Your Android project is now a basic "Hello World" app that contains some default files.
To run the app, continue to the <a href="running-app.html">next lesson</a>.</p>
<p class="note"><strong>Tip:</strong> Add the <code>platform-tools/</code> as well as the
diff --git a/docs/html/training/basics/firstapp/index.jd b/docs/html/training/basics/firstapp/index.jd
index 4c1a0dc3..1b49096 100644
--- a/docs/html/training/basics/firstapp/index.jd
+++ b/docs/html/training/basics/firstapp/index.jd
@@ -8,21 +8,21 @@
@jd:body
-<div id="tb-wrapper">
-<div id="tb">
-
-<h2>Dependencies and prerequisites</h2>
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>Dependencies and prerequisites</h2>
<ul>
<li><a href="http://developer.android.com/sdk/index.html">Android SDK</a></li>
- <li><a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> 20.0.0 or higher
+ <li><a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> 22.6.2 or higher
(if you're using Eclipse)</li>
</ul>
-
-</div>
-</div>
-
-<p>Welcome to Android application development!</p>
+
+</div>
+</div>
+
+<p>Welcome to Android application development!</p>
<p>This class teaches you how to build your first Android app. You’ll learn how to create an Android
project and run a debuggable version of the app. You'll also learn some fundamentals of Android app
@@ -36,6 +36,10 @@
<li>Download the latest SDK tools and platforms using the SDK Manager.</li>
</ol>
+<p class="note"><strong>Note:</strong> Make sure you install the most recent versions of the ADT
+plugin and the Android SDK before you start this class. The procedures described in this class may
+not apply to earlier versions.</p>
+
<p>If you haven't already done these tasks, start by downloading the
<a href="{@docRoot}sdk/index.html">Android SDK</a> and following the install steps.
Once you've finished the setup, you're ready to begin this class.</p>
diff --git a/docs/html/training/basics/firstapp/starting-activity.jd b/docs/html/training/basics/firstapp/starting-activity.jd
index 9aa25a3..27d2c10 100644
--- a/docs/html/training/basics/firstapp/starting-activity.jd
+++ b/docs/html/training/basics/firstapp/starting-activity.jd
@@ -10,9 +10,9 @@
<!-- This is the training bar -->
-<div id="tb-wrapper">
-<div id="tb">
-
+<div id="tb-wrapper">
+<div id="tb">
+
<h2>This lesson teaches you to</h2>
<ol>
@@ -30,10 +30,10 @@
<li><a href="{@docRoot}sdk/installing/index.html">Installing the
SDK</a></li>
</ul>
-
-
-</div>
-</div>
+
+
+</div>
+</div>
@@ -151,7 +151,7 @@
</pre>
<p class="note"><strong>Note:</strong>
-You now need an import statement for <code>android.widget.EditText</code>.
+You now need an import statement for <code>android.widget.EditText</code>.
You'll define the <code>EXTRA_MESSAGE</code> constant in a moment.</p>
<p>An {@link android.content.Intent} can carry a collection of various data types as key-value
@@ -212,7 +212,7 @@
<p>To create a new activity using Eclipse:</p>
<ol>
- <li>Click <strong>New</strong> <img src="{@docRoot}images/tools/eclipse-new.png"
+ <li>Click <strong>New</strong> <img src="{@docRoot}images/tools/eclipse-new.png"
style="vertical-align:baseline;margin:0" /> in the toolbar.</li>
<li>In the window that appears, open the <strong>Android</strong> folder
and select <strong>Android Activity</strong>. Click <strong>Next</strong>.</li>
@@ -247,15 +247,19 @@
<li>There's also an implementation of {@link android.app.Activity#onOptionsItemSelected
onOptionsItemSelected()} which handles the behavior for the action bar's <em>Up</em> behavior.
Keep this one the way it is.</li>
- <li>There's also a <code>PlaceholderFragment</code> class that extends
+ <li>There's also a <code>PlaceholderFragment</code> class that extends
{@link android.app.Fragment}. You will not need this class in the final version of this
activity.</li>
</ul>
-<p>Fragments decompose application functionality and UI into reusable modules. For more
-information on fragments, see the <a href="{@docRoot}guide/components/fragments.html">Fragments
+<p>Fragments decompose application functionality and UI into reusable modules. For more
+information on fragments, see the <a href="{@docRoot}guide/components/fragments.html">Fragments
API Guide</a>. The final version of this activity does not use fragments.</p>
+<p class="note"><strong>Note:</strong> Your activity may look different if you did not use
+the latest version of the ADT plugin. Make sure you install the latest version of the
+<a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT plugin</a> to complete this tutorial.</p>
+
<p>The {@code DisplayMessageActivity} class should now look like this:</p>
<pre>
diff --git a/docs/html/wear/design/index.html b/docs/html/wear/design/index.html
deleted file mode 100644
index 9952490..0000000
--- a/docs/html/wear/design/index.html
+++ /dev/null
@@ -1,607 +0,0 @@
-<!DOCTYPE html>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Design Principles of Android Wear | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display"> </div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Design Principles of Android Wear</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <style>
-h3 {
- padding:30px 0 10px;
-}
-</style>
-<p>
-Android wearables provide just the right information at just the right time, allowing you to be connected to the virtual world and present in the real world.</p>
-
-<img src="/wear/images/05_images.png" height="200" width="169" style="float:right;clear:right;margin:0 0 60px 60px" />
-
-<p>Here you’ll find some guidelines for designing great user experiences on the Android Wear
-platform. Designing for Android Wear is substantially different than designing for phones or
-tablets, so we’ll start by describing how your content can work in tandem with the overall
-Android Wear vision. To better understand the user experience on Android Wear, also be sure
-to read the <a href="/wear/design/user-interface.html">UI Overview</a>.</p>
-
-
-<img src="/wear/images/02_notifications.png" height="200" width="169" style="float:right;clear:right;margin:0 0 20px 60px" />
-
-
-
-<p>Android Wear experiences are:</p>
-
-<ul>
- <li><strong>Contextually aware and smart.</strong> These devices bring a new level of awareness to computing. Rather than requiring attention and input from users, Android wearables are aware of their situation and state, and helpfully display the right information at the right time. <em>Timely, relevant, specific</em>.</li>
-
- <li><strong>Glanceable.</strong> Wearable devices are used all throughout the day, even when they sit in our peripheral vision. Effective apps provide the maximum payload of information with a minimum of fuss, optimized to provide tiny snippets of relevant information throughout the day. <em>Short, sharp, immediate.</em></li>
-
- <li><strong>Zero/low interaction.</strong> Staying true to the strengths afforded by a smaller form factor, Android Wear focuses on simple interactions, only requiring input by the user when absolutely necessary. Most inputs are based around touch swipes or voice, and inputs requiring fine-grained motor skills are avoided. <em>Gestural, simple, fast.</em></li>
-
- <li><strong>Helpful.</strong> Android Wear is like a great personal assistant: it knows you and your preferences, it only interrupts you when absolutely necessary, and it’s always on hand to provide a ready answer. <em>Efficient, respectful, responsive.</em></li>
-</ul>
-
-
-<p>
-By providing a smart connection to the rest of the world while respecting the user’s attention, Android Wear feels personal and global, simple and smart, unobtrusive and ever-ready. Notifications that respect these principles will feel most at home in the overall Android Wear experience.
-</p>
-
-
-
-<h2 id="Notifications" style="clear:both">Notification UI Patterns</h2>
-
-<p>Android notifications appear as cards in the main stream and form the core of the Android Wear experience. Many of the main <a href="http://developer.android.com/design/patterns/notifications.html">Android Design guidelines for notifications</a> apply in Android Wear. Be respectful of users' attention and aware of how unnecessary interruptions will reflect on your application’s reputation.</p>
-
-<p>Omit needless text from your notifications. Design for glanceability, not reading. Use words and phrases, not sentences. Show, don't tell: where possible use simple icons, glyphs, and visualizations to convey your message.</p>
-<img src="/wear/images/circle_message2.png" height="200" style="float:right;clear:right;margin:0 0 20px 60px" />
-
-<p>In some cases, particularly with messaging applications, cards will contain dynamic content which may not fit on a single screen. In these cases the content will be automatically truncated to fit on the card and the user may tap to expand, so the full message should be provided.</p>
-
-<p>Notification priority should reflect the urgency of your notification, with only time-sensitive notifications carrying a high priority. Active notifications – that is, those that cause the device to vibrate – should only be used in cases that need the user's urgent attention or action (e.g. a time-based reminder, a message from a friend). Non-urgent notifications (e.g. a transit times card, daily pedometer count, social network updates) should be silently added to the card stream.</p>
-
-
-
-
-<h3 id="NotifictionActions" style="clear:both">Actions</h3>
-
-<img src="/wear/images/circle_message2_reply.png" height="200" style="float:right;clear:right;margin:0 0 20px 40px" />
-
-<p>Actions appear to the right of your notification, allowing the user to act on your notification. Up to three actions are permitted. The most-used action should be placed first, so that it is a single swipe away from your content.</p>
-
-<p>Actions consist of an icon and a caption. Icons should be PNG files, white on transparent background, 64 × 64 DP. Captions should be verb-driven and short, and will be automatically truncated at one line.</p>
-
-<p>Actions are optional. Many useful notifications will not need to include actions at all.</p>
-
-<p>For developer details about action buttons, see <a href="/wear/notifications/creating.html">Creating
-Notifications for Android Wear</a>.</p>
-
-
-
-
-
-
-<h3 id="Images" style="clear:both">Images</h3>
-
-<img src="/wear/images/circle_badge_B.png" height="200" style="float:right;clear:right;margin:0 0 20px 40px" />
-
-
-<p>Images appear behind cards in the stream, providing context and additional glanceability. Your image should support the core message of the notification; for example, a card about a sports team could include the team color and logo; a message from a contact should display that person's profile photo.</p>
-
-<p>Bear in mind that the card will partially cover the lower part of the image. Images should be at least 320 × 320 pixels at hdpi. Image backgrounds move when horizontally swiped, so landscape-oriented images work better on notifications that include pages or actions.</p>
-
-<p>To add large images, use <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#setLargeIcon(android.graphics.Bitmap)">setLargeIcon()</a></code> with any notification, as
-shown in <a href="/wear/notifications/creating.html">Creating
-Notifications for Android Wear</a>.</p>
-
-
-
-
-
-<h3 id="AppIcons" style="clear:both">Application Icons</h3>
-
-<img src="/wear/images/07_appicons.png" height="200" style="float:right;margin:0 0 20px 60px" />
-
-<p>Your application’s launcher icon will be automatically placed on the card, identifying your notification. Do not use the notification title or background image to identify or brand your application. Instead, allow your icon to identify itself and focus on delivering a clear, succinct message in the card and image. You can choose not to display this icon using
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setHintHideIcon(boolean)"><code>setHintHideIcon()</code></a>.
-</p>
-
-
-
-
-
-
-
-<h3 id="NotificationPages" style="clear:both">Pages</h3>
-
-<p>Pages are additional cards that can appear to the right of your main card in the stream. If your core message is longer than a short snippet, do not sacrifice glanceability by packing a lot of information into your primary notification. Instead, use pages to provide additional content.</p>
-
-<img src="/wear/images/08_pages.png" height="200" style="float:left;margin:0 0 20px 0px" />
-<img src="/wear/images/09_pages.png" height="200" style="float:left;margin:0 0 20px 60px" />
-<img src="/wear/images/10_pages.png" height="200" style="float:left;margin:0 0 20px 60px" />
-
-<p style="clear:left">Pages appear immediately to the right of the main notification card. They are typically used to provide additional details or alternate views of the main card’s content. For example:</p>
-<ul>
- <li>A current weather card might provide an additional page showing a three-day forecast.</li>
- <li>A next train departure card might provide an additional page showing subsequent departures times.</li>
- <li>A daily step count card might provide an additional page showing the same measurement in calories and distance.</li>
-</ul>
-
-<p>There is no imposed limit on the number of pages you may add. However, notifications that provide actions should show no more than three pages to ensure that the actions remain easily accessible.</p>
-
-<p>Pages are optional. Many useful notifications will not need to include pages at all.</p>
-
-<p>For developer details about pages, see
-described in <a href="/wear/notifications/pages.html">Adding
-Pages to a Notification</a>.</p>
-
-
-
-
-
-<h3 id="NotificationStacks" style="clear:both">Notification Stacks</h3>
-
-<img src="/wear/images/11_bundles_B.png" height="200" style="float:right;margin:0 0 20px 60px" />
-<img src="/wear/images/11_bundles_A.png" height="200" style="float:right;margin:0 0 20px 60px" />
-
-<p>Stacks may be used to collect multiple notifications from the same application into a single stack of cards. Whereas pages are used to provide additional detail on a single notification, stacks are used to collect multiple sibling notifications together. A stack may be expanded by the user to access each individual card contained within.</p>
-
-<p>Stacks are a way of adding multiple useful notifications without overwhelming the user’s stream. If your application may produce multiple concurrent notifications, consider combining them into a stack.</p>
-
-<p>Each notification within a stack can contain separate pages and separate actions that are relevant to that specific notification. The user can access these actions after expanding that notification's card within the stack.</p>
-
-<p>For developer details about stacks, see
-described in <a href="/wear/notifications/stacks.html">Stacking
-Notifications</a>.</p>
-
-
-
-
-
-
-<h3 id="VoiceReplies" style="clear:both">Voice Replies</h3>
-
-
-<img src="/wear/images/circle_voice_B.png" height="200" style="float:right;margin:0 0 20px 40px" />
-<img src="/wear/images/circle_voice_A.png" height="200" style="float:right;margin:0 0 20px 40px" />
-
-<p>Voice replies are primarily used by messaging applications to provide a hands-free way of dictating a short message. You can also provide a up to five suggested replies or “canned responses” that are useful in a wide range of cases. These canned responses can be tapped by the user, allowing for a fast method of sending simple replies in cases where speaking may not be desirable.</p>
-
-<p>You should attempt to cover a range of simple, neutral replies in your choices. Longer voice replies may be automatically truncated in the Voice reply UI.</p>
-
-<p>For developer details about enabling voice replies, see
-described in <a href="/wear/notifications/remote-input.html">Receiving Voice Input from
-a Notification</a>.</p>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a> |
- <a href="/legal.html">Legal</a> |
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/design/index.jd b/docs/html/wear/design/index.jd
new file mode 100644
index 0000000..247cc87
--- /dev/null
+++ b/docs/html/wear/design/index.jd
@@ -0,0 +1,173 @@
+page.title=Design Principles of Android Wear
+
+@jd:body
+
+<style>
+h3 {
+ padding:30px 0 10px;
+}
+</style>
+<p>
+Android wearables provide just the right information at just the right time, allowing you to be connected to the virtual world and present in the real world.</p>
+
+<img src="{@docRoot}wear/images/05_images.png" height="200" width="169" style="float:right;clear:right;margin:0 0 60px 60px" />
+
+<p>Here you’ll find some guidelines for designing great user experiences on the Android Wear
+platform. Designing for Android Wear is substantially different than designing for phones or
+tablets, so we’ll start by describing how your content can work in tandem with the overall
+Android Wear vision. To better understand the user experience on Android Wear, also be sure
+to read the <a href="{@docRoot}wear/design/user-interface.html">UI Overview</a>.</p>
+
+
+<img src="{@docRoot}wear/images/02_notifications.png" height="200" width="169" style="float:right;clear:right;margin:0 0 20px 60px" />
+
+
+
+<p>Android Wear experiences are:</p>
+
+<ul>
+ <li><strong>Contextually aware and smart.</strong> These devices bring a new level of awareness to computing. Rather than requiring attention and input from users, Android wearables are aware of their situation and state, and helpfully display the right information at the right time. <em>Timely, relevant, specific</em>.</li>
+
+ <li><strong>Glanceable.</strong> Wearable devices are used all throughout the day, even when they sit in our peripheral vision. Effective apps provide the maximum payload of information with a minimum of fuss, optimized to provide tiny snippets of relevant information throughout the day. <em>Short, sharp, immediate.</em></li>
+
+ <li><strong>Zero/low interaction.</strong> Staying true to the strengths afforded by a smaller form factor, Android Wear focuses on simple interactions, only requiring input by the user when absolutely necessary. Most inputs are based around touch swipes or voice, and inputs requiring fine-grained motor skills are avoided. <em>Gestural, simple, fast.</em></li>
+
+ <li><strong>Helpful.</strong> Android Wear is like a great personal assistant: it knows you and your preferences, it only interrupts you when absolutely necessary, and it’s always on hand to provide a ready answer. <em>Efficient, respectful, responsive.</em></li>
+</ul>
+
+
+<p>
+By providing a smart connection to the rest of the world while respecting the user’s attention, Android Wear feels personal and global, simple and smart, unobtrusive and ever-ready. Notifications that respect these principles will feel most at home in the overall Android Wear experience.
+</p>
+
+
+
+<h2 id="Notifications" style="clear:both">Notification UI Patterns</h2>
+
+<p>Android notifications appear as cards in the main stream and form the core of the Android Wear experience. Many of the main <a href="http://developer.android.com/design/patterns/notifications.html">Android Design guidelines for notifications</a> apply in Android Wear. Be respectful of users' attention and aware of how unnecessary interruptions will reflect on your application’s reputation.</p>
+
+<p>Omit needless text from your notifications. Design for glanceability, not reading. Use words and phrases, not sentences. Show, don't tell: where possible use simple icons, glyphs, and visualizations to convey your message.</p>
+<img src="{@docRoot}wear/images/circle_message2.png" height="200" style="float:right;clear:right;margin:0 0 20px 60px" />
+
+<p>In some cases, particularly with messaging applications, cards will contain dynamic content which may not fit on a single screen. In these cases the content will be automatically truncated to fit on the card and the user may tap to expand, so the full message should be provided.</p>
+
+<p>Notification priority should reflect the urgency of your notification, with only time-sensitive notifications carrying a high priority. Active notifications – that is, those that cause the device to vibrate – should only be used in cases that need the user's urgent attention or action (e.g. a time-based reminder, a message from a friend). Non-urgent notifications (e.g. a transit times card, daily pedometer count, social network updates) should be silently added to the card stream.</p>
+
+
+
+
+<h3 id="NotifictionActions" style="clear:both">Actions</h3>
+
+<img src="{@docRoot}wear/images/circle_message2_reply.png" height="200" style="float:right;clear:right;margin:0 0 20px 40px" />
+
+<p>Actions appear to the right of your notification, allowing the user to act on your notification. Up to three actions are permitted. The most-used action should be placed first, so that it is a single swipe away from your content.</p>
+
+<p>Actions consist of an icon and a caption. Icons should be PNG files, white on transparent
+background, 32 × 32 dp (with 8 dp padding), as specified in the <a
+href="/design/style/iconography.html#action-bar">Iconography</a> design guide for action bar
+icons. Captions should be verb-driven and short, and will be automatically truncated at one line.
+</p>
+
+<p>Actions are optional. Many useful notifications will not need to include actions at all.</p>
+
+<p>For developer details about action buttons, see <a href="{@docRoot}wear/notifications/creating.html">Creating
+Notifications for Android Wear</a>.</p>
+
+
+
+
+
+
+<h3 id="Images" style="clear:both">Images</h3>
+
+<img src="{@docRoot}wear/images/circle_badge_B.png" height="200" style="float:right;clear:right;margin:0 0 20px 40px" />
+
+
+<p>Images appear behind cards in the stream, providing context and additional glanceability. Your image should support the core message of the notification; for example, a card about a sports team could include the team color and logo; a message from a contact should display that person's profile photo.</p>
+
+<p>Bear in mind that the card will partially cover the lower part of the image. Images should
+be sized as appropriate for the notification appearance on handsets, which is 64 x 64 dp. Image backgrounds move when horizontally swiped, so landscape-oriented images work better on notifications that include pages or actions.</p>
+
+<p>To add large images, use {@link android.support.v4.app.NotificationCompat.Builder#setLargeIcon
+setLargeIcon()} with any notification, as
+shown in <a href="{@docRoot}wear/notifications/creating.html">Creating
+Notifications for Android Wear</a>.</p>
+
+
+
+
+
+<h3 id="AppIcons" style="clear:both">Application Icons</h3>
+
+<img src="{@docRoot}wear/images/07_appicons.png" height="200" style="float:right;margin:0 0 20px 60px" />
+
+<p>Your application’s launcher icon will be automatically placed on the card, identifying your notification. Do not use the notification title or background image to identify or brand your application. Instead, allow your icon to identify itself and focus on delivering a clear, succinct message in the card and image. You can choose not to display this icon using
+ <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setHintHideIcon(boolean)"><code>setHintHideIcon()</code></a>.
+</p>
+
+
+
+
+
+
+
+<h3 id="NotificationPages" style="clear:both">Pages</h3>
+
+<p>Pages are additional cards that can appear to the right of your main card in the stream. If your core message is longer than a short snippet, do not sacrifice glanceability by packing a lot of information into your primary notification. Instead, use pages to provide additional content.</p>
+
+<img src="{@docRoot}wear/images/08_pages.png" height="200" style="float:left;margin:0 0 20px 0px" />
+<img src="{@docRoot}wear/images/09_pages.png" height="200" style="float:left;margin:0 0 20px 60px" />
+<img src="{@docRoot}wear/images/10_pages.png" height="200" style="float:left;margin:0 0 20px 60px" />
+
+<p style="clear:left">Pages appear immediately to the right of the main notification card. They are typically used to provide additional details or alternate views of the main card’s content. For example:</p>
+<ul>
+ <li>A current weather card might provide an additional page showing a three-day forecast.</li>
+ <li>A next train departure card might provide an additional page showing subsequent departures times.</li>
+ <li>A daily step count card might provide an additional page showing the same measurement in calories and distance.</li>
+</ul>
+
+<p>There is no imposed limit on the number of pages you may add. However, notifications that provide actions should show no more than three pages to ensure that the actions remain easily accessible.</p>
+
+<p>Pages are optional. Many useful notifications will not need to include pages at all.</p>
+
+<p>For developer details about pages, see
+described in <a href="{@docRoot}wear/notifications/pages.html">Adding
+Pages to a Notification</a>.</p>
+
+
+
+
+
+<h3 id="NotificationStacks" style="clear:both">Notification Stacks</h3>
+
+<img src="{@docRoot}wear/images/11_bundles_B.png" height="200" style="float:right;margin:0 0 20px 60px" />
+<img src="{@docRoot}wear/images/11_bundles_A.png" height="200" style="float:right;margin:0 0 20px 60px" />
+
+<p>Stacks may be used to collect multiple notifications from the same application into a single stack of cards. Whereas pages are used to provide additional detail on a single notification, stacks are used to collect multiple sibling notifications together. A stack may be expanded by the user to access each individual card contained within.</p>
+
+<p>Stacks are a way of adding multiple useful notifications without overwhelming the user’s stream. If your application may produce multiple concurrent notifications, consider combining them into a stack.</p>
+
+<p>Each notification within a stack can contain separate pages and separate actions that are relevant to that specific notification. The user can access these actions after expanding that notification's card within the stack.</p>
+
+<p>For developer details about stacks, see
+described in <a href="{@docRoot}wear/notifications/stacks.html">Stacking
+Notifications</a>.</p>
+
+
+
+
+
+
+<h3 id="VoiceReplies" style="clear:both">Voice Replies</h3>
+
+
+<img src="{@docRoot}wear/images/circle_voice_B.png" height="200" style="float:right;margin:0 0 20px 40px" />
+<img src="{@docRoot}wear/images/circle_voice_A.png" height="200" style="float:right;margin:0 0 20px 40px" />
+
+<p>Voice replies are primarily used by messaging applications to provide a hands-free way of dictating a short message. You can also provide a up to five suggested replies or “canned responses” that are useful in a wide range of cases. These canned responses can be tapped by the user, allowing for a fast method of sending simple replies in cases where speaking may not be desirable.</p>
+
+<p>You should attempt to cover a range of simple, neutral replies in your choices. Longer voice replies may be automatically truncated in the Voice reply UI.</p>
+
+<p>For developer details about enabling voice replies, see
+described in <a href="{@docRoot}wear/notifications/remote-input.html">Receiving Voice Input from
+a Notification</a>.</p>
diff --git a/docs/html/wear/design/user-interface.html b/docs/html/wear/design/user-interface.html
deleted file mode 100644
index c23d79c..0000000
--- a/docs/html/wear/design/user-interface.html
+++ /dev/null
@@ -1,498 +0,0 @@
-<!DOCTYPE html>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>UI Overview | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<link rel="stylesheet" type="text/css" href="/wear/css/wear.css">
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display"> </div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >UI Overview</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <style>
-h3 {
- padding:30px 0 10px;
-}
-</style>
-
-<p>A new form factor deserves a new UI model. At a high level, the Android Wear UI consists of two
-main spaces centered around the core functions of <strong>Suggest</strong> and
-<strong>Demand</strong>. Your application will have an important role to play in both of these
-spaces.</p>
-
-
-
-<h3 id="Stream">Suggest: The Context Stream</h3>
-
-<div class="wear-inset-video-container" style="float:right;margin:0 -22px 60px 40px">
- <img class="wear-bezel-only" src="/wear/images/screens/bezel.png" alt="">
- <img class="gif" src="/wear/images/screens/stream.gif">
-</div>
-
-<p>The context stream is a vertical list of cards, each showing a useful or timely piece of
-information. Much like Google Now on Android phones and tablets, users swipe vertically to navigate
-from card to card for a brief and comprehensive update about what's important to them. Only one card
-is displayed on screen at a time, and background images are used to provide additional visual
-information. Your application can create cards and inject them into the stream when they are most
-likely to be useful.</p>
-
-<p>Cards in the stream are more than simple notifications. They can be swiped horizontally to
-reveal additional pages. Further horizontal swiping may reveal tappable buttons, allowing the user
-to take action on the notification. Cards can also be dismissed by swiping left to right, removing
-them from the stream until the next time they have useful information to display.
-In the emulator, hovering the mouse over the top of the screen illuminates a blue bar at
-the top of the device that takes you home when clicked.</p>
-
-
-
-<h3 id="CueCard">Demand: The Cue Card</h3>
-
-<div class="wear-inset-video-container" style="float:right;margin:0 -22px 60px 40px">
- <img class="wear-bezel-only" src="/wear/images/screens/bezel.png" alt="">
- <img class="gif" src="/wear/images/screens/cuecard.gif">
-</div>
-
-<p>For cases where the context stream can't anticipate what the user would like to do, the cue card
-allows users to speak to their device. The cue card is opened by saying, "Ok Google" or by tapping
-on the "g" icon on the home screen. Swiping up on the cue card shows a list of actions, which can
-also be tapped.</p>
-
-<p>The list of actions includes Android intents for voice actions. The upcoming Android Wear SDK
-will enable developers to match their applications to these intents so users can perform actions
-using these voice commands. Multiple applications may register for a single voice intent, and users
-will have the opportunity to choose which application they prefer to use.</p>
-
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a> |
- <a href="/legal.html">Legal</a> |
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/design/user-interface.jd b/docs/html/wear/design/user-interface.jd
new file mode 100644
index 0000000..2a3e9ef
--- /dev/null
+++ b/docs/html/wear/design/user-interface.jd
@@ -0,0 +1,58 @@
+page.title=UI Overview
+page.customHeadTag=<link rel="stylesheet" type="text/css" href="/wear/css/wear.css">
+
+@jd:body
+
+<style>
+h3 {
+ padding:30px 0 10px;
+}
+</style>
+
+<p>A new form factor deserves a new UI model. At a high level, the Android Wear UI consists of two
+main spaces centered around the core functions of <strong>Suggest</strong> and
+<strong>Demand</strong>. Your application will have an important role to play in both of these
+spaces.</p>
+
+
+
+<h3 id="Stream">Suggest: The Context Stream</h3>
+
+<div class="wear-inset-video-container" style="float:right;margin:0 -22px 60px 40px">
+ <img class="wear-bezel-only" src="{@docRoot}wear/images/screens/bezel.png" alt="">
+ <img class="gif" src="{@docRoot}wear/images/screens/stream.gif">
+</div>
+
+<p>The context stream is a vertical list of cards, each showing a useful or timely piece of
+information. Much like Google Now on Android phones and tablets, users swipe vertically to navigate
+from card to card for a brief and comprehensive update about what's important to them. Only one card
+is displayed on screen at a time, and background images are used to provide additional visual
+information. Your application can create cards and inject them into the stream when they are most
+likely to be useful.</p>
+
+<p>Cards in the stream are more than simple notifications. They can be swiped horizontally to
+reveal additional pages. Further horizontal swiping may reveal tappable buttons, allowing the user
+to take action on the notification. Cards can also be dismissed by swiping left to right, removing
+them from the stream until the next time they have useful information to display.
+In the emulator, hovering the mouse over the top of the screen illuminates a blue bar at
+the top of the device that takes you home when clicked.</p>
+
+
+
+<h3 id="CueCard">Demand: The Cue Card</h3>
+
+<div class="wear-inset-video-container" style="float:right;margin:0 -22px 60px 40px">
+ <img class="wear-bezel-only" src="{@docRoot}wear/images/screens/bezel.png" alt="">
+ <img class="gif" src="{@docRoot}wear/images/screens/cuecard.gif">
+</div>
+
+<p>For cases where the context stream can't anticipate what the user would like to do, the cue card
+allows users to speak to their device. The cue card is opened by saying, "Ok Google" or by tapping
+on the "g" icon on the home screen. Swiping up on the cue card shows a list of actions, which can
+also be tapped.</p>
+
+<p>The list of actions includes Android intents for voice actions. The upcoming Android Wear SDK
+will enable developers to match their applications to these intents so users can perform actions
+using these voice commands. Multiple applications may register for a single voice intent, and users
+will have the opportunity to choose which application they prefer to use.</p>
+
diff --git a/docs/html/wear/images/laptop-bridge.png b/docs/html/wear/images/laptop-bridge.png
index b481224..083b82b 100644
--- a/docs/html/wear/images/laptop-bridge.png
+++ b/docs/html/wear/images/laptop-bridge.png
Binary files differ
diff --git a/docs/html/wear/images/screens/cuecard.gif b/docs/html/wear/images/screens/cuecard.gif
index 4b3d2f3..de1f53b 100644
--- a/docs/html/wear/images/screens/cuecard.gif
+++ b/docs/html/wear/images/screens/cuecard.gif
Binary files differ
diff --git a/docs/html/wear/images/screens/stream.gif b/docs/html/wear/images/screens/stream.gif
index 656a277..3c18775 100644
--- a/docs/html/wear/images/screens/stream.gif
+++ b/docs/html/wear/images/screens/stream.gif
Binary files differ
diff --git a/docs/html/wear/index.html b/docs/html/wear/index.jd
similarity index 66%
rename from docs/html/wear/index.html
rename to docs/html/wear/index.jd
index 712e1af..a6a6460 100644
--- a/docs/html/wear/index.html
+++ b/docs/html/wear/index.jd
@@ -1,286 +1,12 @@
-<!DOCTYPE html>
+page.title=Android Wear
+page.viewport_width=970
+fullpage=true
+no_footer_links=true
+page.customHeadTag=<link rel="stylesheet" type="text/css" href="/wear/css/wear.css">
+@jd:body
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Android Wear | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<link rel="stylesheet" type="text/css" href="/wear/css/wear.css">
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display"> </div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div id="body-content">
-
-
-
-
-<div class="fullpage" >
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <style>
+<style>
.fullpage>#footer,
#jd-content>.content-footer.wrap {
display:none;
@@ -297,8 +23,8 @@
</div>
<script src="//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
<div id="ytapiplayer">
- <a href="http://www.youtube.com/watch?v=i2uvYI6blEE"><img width=600
- src="https://i1.ytimg.com/vi/i2uvYI6blEE/maxresdefault.jpg"></a><!--You need Flash player 8+ and JavaScript enabled to view this video. -->
+ <a href="http://www.youtube.com/watch?v=0xQ3y902DEQ"><img width=940
+ src="https://i1.ytimg.com/vi/0xQ3y902DEQ/maxresdefault.jpg"></a><!--You need Flash player 8+ and JavaScript enabled to view this video. -->
</div>
</div>
</div>
@@ -346,9 +72,14 @@
});
$("#icon-video-close").on("click", function() {
ytplayer = document.getElementById("ytapiplayer");
- ytplayer.stopVideo();
- $(ytplayer).hide();
- $("#video-container").fadeOut(400);
+ try {
+ ytplayer.stopVideo();
+ $(ytplayer).hide();
+ $("#video-container").fadeOut(400);
+ } catch(e) {
+ console.log('Video not available');
+ $("#video-container").fadeOut(400);
+ }
});
</script>
</div>
@@ -466,10 +197,10 @@
</div>
<p>
- You can also trigger your notifications contextually using existing Android APIs. For example, use <a href="/training/location/geofencing.html">geofences</a> to provide glanceable information to your users when they are at home, or use the <a href="/training/location/activity-recognition.html">activity detection APIs</a> to send messages to your users’ wrists while they are bicycling.
+ You can also trigger your notifications contextually using existing Android APIs. For example, use <a href="{@docRoot}training/location/geofencing.html">geofences</a> to provide glanceable information to your users when they are at home, or use the <a href="{@docRoot}training/location/activity-recognition.html">activity detection APIs</a> to send messages to your users’ wrists while they are bicycling.
</p>
- <p>See the <a href="/wear/design/index.html">Android Wear Developer Preview Design Principles</a> for more suggestions on creating great wearable experiences.</p>
+ <p>See the <a href="{@docRoot}wear/design/index.html">Android Wear Developer Preview Design Principles</a> for more suggestions on creating great wearable experiences.</p>
</div>
</div> <!-- end .wrap -->
@@ -650,7 +381,7 @@
<div class="g-plusone" data-size="medium"></div>
</div>
</div>
- <div id="footer" class="wrap" style="width:940px;position:relative;top:-35px">
+ <div id="footer" class="wrap" style="width:940px;position:relative;top:-35px;z-index:-1">
<div id="copyright">
Except as noted, this content is
licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
@@ -672,63 +403,3 @@
});
</script>
-
- </div>
-
- <div class="content-footer wrap"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-16" style="padding-top:4px">
- <style>#___plusone_0 {float:right !important;}</style>
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" style="width:940px">
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/license.html b/docs/html/wear/license.jd
similarity index 63%
rename from docs/html/wear/license.html
rename to docs/html/wear/license.jd
index c7569bc..b07dacf 100644
--- a/docs/html/wear/license.html
+++ b/docs/html/wear/license.jd
@@ -1,379 +1,9 @@
-<!DOCTYPE html>
+page.title=Developer Preview License Agreement
+@jd:body
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Developer Preview License Agreement | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display"> </div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Developer Preview License Agreement</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <div class="sdk-terms" style="height:auto;border:0;padding:0;width:700px">
+<div class="sdk-terms" style="height:auto;border:0;padding:0;width:700px">
This is the Android Wear Developer Preview License Agreement.
1. Introduction
@@ -510,72 +140,3 @@
14.7 This License Agreement, and your relationship with Google under this License Agreement, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Google agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California to resolve any legal matter arising from this License Agreement. Notwithstanding this, you agree that Google shall still be allowed to apply for injunctive remedies (or an equivalent type of urgent legal relief) in any jurisdiction.
</div>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a> |
- <a href="/legal.html">Legal</a> |
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/notifications/creating.html b/docs/html/wear/notifications/creating.html
deleted file mode 100644
index e83b57a..0000000
--- a/docs/html/wear/notifications/creating.html
+++ /dev/null
@@ -1,722 +0,0 @@
-<!DOCTYPE html>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Creating Notifications for Android Wear | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display"> </div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Creating Notifications for Android Wear</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <p>When an Android device such as a phone or tablet is connected to an Android wearable,
-all notifications are shared between the devices by default. On the Android wearable, each
-notification appears as a new card in the <a href="/wear/design/user-interface.html#Stream"
->context stream</a>.</p>
-
-<img src="/wear/images/notification_phone@2x.png" width="700" height="265" />
-
-
-<p>So without any effort, your app notifications are available to users on Android Wear.
-However, you can enhance the user experience in several ways. For instance,
-if users may respond to a notification by entering text, such as to reply to
-a message, you can add the ability for users to reply by voice directly from the
-wearable.</p>
-
-<p>To help you provide the best user experience
-for your notifications on Android Wear, this guide shows you how to
-build notifications using standard templates in
-the <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html">NotificationCompat.Builder</a></code> APIs, plus how to begin
-extending your notification's capabilities for the wearable user experience.</p>
-
-<p class="note"><strong>Note:</strong>
-Notifications using <code><a href="/reference/android/widget/RemoteViews.html">RemoteViews</a></code> are stripped of custom
-layouts and the system uses only the text and icons in the
-<code><a href="/reference/android/app/Notification.html">Notification</a></code> object to
-display the notification in a card. However, custom card layouts will be supported by
-the official Android Wear SDK that is coming later.</p>
-</div>
-
-
-
-
-<h2 id="Import">Import the Necessary Classes</h2>
-
-<p>To begin development, you must first complete the instructions in the <a
-href="/wear/preview/start">Get Started with the Developer Preview</a> document.
-As mentioned in that document, your app must include
-both the <a href="http://developer.android.com/tools/support-library/features.html#v4">v4 support
-library</a> and the Developer Preview support library. So to get started,
-you should include the following imports in your project code:</p>
-
-<pre>
-import android.preview.support.wearable.notifications.*;
-import android.preview.support.v4.app.NotificationManagerCompat;
-import android.support.v4.app.NotificationCompat;
-</pre>
-
-<p class="caution"><strong>Caution:</strong>
-The APIs in the current Android Wear Developer Preview are intended for <b>development and testing purposes only</b>, not for production apps. Google may change this Developer Preview significantly prior to the official release of the Android Wear SDK. You may not publicly distribute or ship any application using this Developer Preview, as this Developer Preview will no longer be supported after the official SDK is released (which will cause applications based only on the Developer Preview to break).</p>
-
-
-
-<h2 id="NotificationBuilder">Create Notifications with the Notification Builder</h2>
-
-<p>The <a href="http://developer.android.com/tools/support-library/features.html#v4">v4
-support library</a> allows you to create notifications using the latest notification features
-such as action buttons and large icons, while remaining compatible with Android 1.6 (API level
-4) and higher.</p>
-
-
-<p>For example, here's some code that creates and issues a notification using the
-<code><a href="/reference/android/support/v4/app/NotificationCompat.html">NotificationCompat</a></code> APIs combined with the new
-<a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">
-<code>NotificationManagerCompat</code></a> API:</p>
-
-
-<pre>
-int notificationId = 001;
-// Build intent for notification content
-Intent viewIntent = new Intent(this, ViewEventActivity.class);
-viewIntent.putExtra(EXTRA_EVENT_ID, eventId);
-PendingIntent viewPendingIntent =
- PendingIntent.getActivity(this, 0, viewIntent, 0);
-
-NotificationCompat.Builder notificationBuilder =
- new NotificationCompat.Builder(this)
- .setSmallIcon(R.drawable.ic_event)
- .setContentTitle(eventTitle)
- .setContentText(eventLocation)
- .setContentIntent(viewPendingIntent);
-
-// Get an instance of the NotificationManager service
-NotificationManagerCompat notificationManager =
- NotificationManagerCompat.from(this);
-
-// Build the notification and issues it with notification manager.
-notificationManager.notify(notificationId, notificationBuilder.build());
-</pre>
-
-<p>When this notification appears on a handheld device, the user can invoke the
-<code><a href="/reference/android/app/PendingIntent.html">PendingIntent</a></code>
-specified by the <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#setContentIntent(android.app.PendingIntent)">setContentIntent()</a></code> method by touching the notification. When this
-notification appears on an Android wearable, the user can swipe the notification to the left to
-reveal the <strong>Open</strong> action, which invokes the intent on the handheld device.</p>
-
-
-
-
-
-
-<img src="/wear/images/circle_email_action.png" height="200" style="float:right;clear:right;margin:0 0 20px 60px" />
-
-<h2 id="ActionButtons">Add Action Buttons</h2>
-
-<p>In addition to the primary content action defined by
-<code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#setContentIntent(android.app.PendingIntent)">setContentIntent()</a></code>, you can add other actions by passing a <code><a href="/reference/android/app/PendingIntent.html">PendingIntent</a></code> to
-the <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#addAction(int, java.lang.CharSequence, android.app.PendingIntent)">addAction()</a></code> method.</p>
-
-<p>For example, the following code shows the same type of notification from above, but adds an
-action to view the event location on a map.</p>
-
-<pre style="clear:right">
-// Build an intent for an action to view a map
-Intent mapIntent = new Intent(Intent.ACTION_VIEW);
-Uri geoUri = Uri.parse("geo:0,0?q=" + Uri.encode(location));
-mapIntent.setData(geoUri);
-PendingIntent mapPendingIntent =
- PendingIntent.getActivity(this, 0, mapIntent, 0);
-
-NotificationCompat.Builder notificationBuilder =
- new NotificationCompat.Builder(this)
- .setSmallIcon(R.drawable.ic_event)
- .setContentTitle(eventTitle)
- .setContentText(eventLocation)
- .setContentIntent(viewPendingIntent)
- <b>.addAction(R.drawable.ic_map,
- getString(R.string.map), mapPendingIntent);</b>
-</pre>
-
-<p>On a handheld device, the action appears as an
-additional button attached to the notification. On an Android wearable, the action appears as
-a large button when the user swipes the notification to the left. When the user taps the action,
-the associated <code><a href="/reference/android/content/Intent.html">Intent</a></code> is invoked on the handheld device.</p>
-
-<p class="note"><strong>Tip:</strong> If your notifications includes a "Reply" action
- (such as for a messaging app), you can enhance the behavior by enabling
- voice input replies directly from the Android wearable. For more information, read
- <a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification</a>.
-</p>
-
-<p>For details about designing action buttons (including the icon specifications), see the
-<a href="/wear/design/index.html#NotifictionActions">Design Principles of Android
-Wear</a>.</p>
-
-
-<h2 id="BigView">Add a Big View</h2>
-
-<img src="/wear/images/06_images.png" height="200" style="float:right;margin:0 0 20px 40px" />
-
-<p>You can insert extended text content
-to your notification by adding one of the "big view" styles to your notification. On a
-handheld device, users can see the big view content by expanding the notification,
-while on Android Wear, the big view content is visible by default.</p>
-
-<p>To add the extended content to your notification, call <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#setStyle(android.support.v4.app.NotificationCompat.Style)">setStyle()</a></code> on the <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html">NotificationCompat.Builder</a></code> object, passing it an instance of either
-<code><a href="/reference/android/support/v4/app/NotificationCompat.BigTextStyle.html">BigTextStyle</a></code> or
-<code><a href="/reference/android/support/v4/app/NotificationCompat.InboxStyle.html">InboxStyle</a></code>.</p>
-
-<p>For example, the following code adds an instance of
-<code><a href="/reference/android/support/v4/app/NotificationCompat.BigTextStyle.html">NotificationCompat.BigTextStyle</a></code> to the event notification,
-in order to include the complete event description (which includes more text than can fit
-into the space provided for <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#setContentText(java.lang.CharSequence)">setContentText()</a></code>).</p>
-
-
-<pre style="clear:right">
-// Specify the 'big view' content to display the long
-// event description that may not fit the normal content text.
-BigTextStyle bigStyle = new NotificationCompat.BigTextStyle();
-bigStyle.bigText(eventDescription);
-
-NotificationCompat.Builder notificationBuilder =
- new NotificationCompat.Builder(this)
- .setSmallIcon(R.drawable.ic_event)
- .setLargeIcon(BitmapFractory.decodeResource(
- getResources(), R.drawable.notif_background))
- .setContentTitle(eventTitle)
- .setContentText(eventLocation)
- .setContentIntent(viewPendingIntent)
- .addAction(R.drawable.ic_map,
- getString(R.string.map), mapPendingIntent)
- <b>.setStyle(bigStyle);</b>
-</pre>
-
-<p>Notice that you can add a large background image to any notification using the
-<code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#setLargeIcon(android.graphics.Bitmap)">setLargeIcon()</a></code>
-method. For more information about designing notifications with large images, see the
-<a href="/wear/design/index.html#Images">Design Principles of Android
-Wear</a>.</p>
-
-
-
-<h2 id="NewFeatures">Add New Features for Wearables</h2>
-
-<p>The Android Wear preview support library provides new APIs that
- allow you to enhance the user experience for notifications on a wearable device. For example,
- you can add additional pages of content that users can view by swiping to the left, or add the ability
-for users to deliver your app a text response using voice input.</p>
-
-<p>To use these new APIs, pass your instance of
-<code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html">NotificationCompat.Builder</a></code> to the
- <a href="/reference/android/preview/support/notifications/WearableNotifications.html"> <code>WearableNotifications.Builder()</code></a> constructor. You can then add new
-features to your notification using the
- <a href="/wear/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"
- ><code>WearableNotifications.Builder</code></a> methods. For example:</p>
-
-<pre>
-// Create a NotificationCompat.Builder for standard notification features
-NotificationCompat.Builder notificationBuilder =
- new NotificationCompat.Builder(mContext)
- .setContentTitle("New mail from " + sender.toString())
- .setContentText(subject)
- .setSmallIcon(R.drawable.new_mail);
-
-// Create a WearablesNotification.Builder to add special functionality for wearables
-Notification notification =
- new WearableNotifications.Builder(notificationBuilder)
- .setHintHideIcon(true)
- .build();
-</pre>
-
-<p>The <a href="/reference/android/preview/support/notifications/WearableNotifications.Builder.html#setBigActionIcon(int)">
- <code>setHintHideIcon()</code></a> method removes your app icon from the notification card.
- This method is just one example of new notification features available from the
- <a href="/wear/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"
- ><code>WearableNotifications.Builder</code></a> class.</p>
-
-<p>When you want to deliver your notifications, be certain to always use the
- <a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">
- <code>NotificationManagerCompat</code></a> API:</p>
-
-<pre>
-// Get an instance of the NotificationManager service
-NotificationManagerCompat notificationManager =
- NotificationManagerCompat.from(this);
-
-// Build the notification and issues it with notification manager.
-notificationManager.notify(notificationId, notification);
-</pre>
-
-<p>If you instead use the framework's <code><a href="/reference/android/app/NotificationManager.html">NotificationManager</a></code>, some
-features from <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"><code>WearableNotifications.Builder</code></a>
-will not work.</p>
-
-<p>To continue enhancing your notifications for wearables using
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder"
- ><code>WearableNotifications.Builder</code></a> and other APIs in the
- preview support library, see the following developer guides:</p>
-
- <dl>
- <dt><a href="/wear/notifications/remote-input.html">Receiving Voice Input
-from a Notification</a></dt>
- <dd>Add an action that receives voice input from the user and delivers the
-transcribed message to your app.</dd>
- <dt><a href="/wear/notifications/pages.html">Adding Pages to a Notification</a></dt>
- <dd>Add additional pages of information that are visible when the user
-swipes to the left.</dd>
- <dt><a href="/wear/notifications/stacks.html">Stacking Notifications</a></dt>
- <dd>Place all similar notifications from your app in a stack, allowing each to be
-viewed individually without adding multiple cards to the card stream.</dd>
- </dl>
-
-
-<div class="next-docs">
-
-<div class="col-12">
- <h2 class="norule">You might also want to read:</h2>
- <dl>
- <dt><a href="/training/notify-user/index.html">Notifying the User</a></dt>
- <dd>Learn more about how to create notifications.</dd>
- <dt><a href="/guide/components/intents-filters.html">Intents and Intent Filters</a></dt>
- <dd>Learn everything you need to know about the <code><a href="/reference/android/content/Intent.html">Intent</a></code>
-APIs, used by notificaton actions.</dd>
- </dl>
-</div>
-</div>
-
-
-</body>
-</html>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a> |
- <a href="/legal.html">Legal</a> |
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/notifications/creating.jd b/docs/html/wear/notifications/creating.jd
new file mode 100644
index 0000000..ce9e117
--- /dev/null
+++ b/docs/html/wear/notifications/creating.jd
@@ -0,0 +1,289 @@
+page.title=Creating Notifications for Android Wear
+
+@jd:body
+
+
+<p>When an Android device such as a phone or tablet is connected to an Android wearable,
+all notifications are shared between the devices by default. On the Android wearable, each
+notification appears as a new card in the <a href="{@docRoot}wear/design/user-interface.html#Stream"
+>context stream</a>.</p>
+
+<img src="{@docRoot}wear/images/notification_phone@2x.png" width="700" height="265" />
+
+
+<p>So without any effort, your app notifications are available to users on Android Wear.
+However, you can enhance the user experience in several ways. For instance,
+if users may respond to a notification by entering text, such as to reply to
+a message, you can add the ability for users to reply by voice directly from the
+wearable.</p>
+
+<p>To help you provide the best user experience
+for your notifications on Android Wear, this guide shows you how to
+build notifications using standard templates in
+the {@link android.support.v4.app.NotificationCompat.Builder} APIs, plus how to begin
+extending your notification's capabilities for the wearable user experience.</p>
+
+<p class="note"><strong>Note:</strong>
+Notifications using {@link android.widget.RemoteViews} are stripped of custom
+layouts and the system uses only the text and icons in the
+{@link android.app.Notification} object to
+display the notification in a card. However, custom card layouts will be supported by
+the official Android Wear SDK that is coming later.</p>
+</div>
+
+
+
+
+<h2 id="Import">Import the Necessary Classes</h2>
+
+<p>To begin development, you must first complete the instructions in the <a
+href="{@docRoot}wear/preview/start.html">Get Started with the Developer Preview</a> document.
+As mentioned in that document, your app must include
+both the <a href="http://developer.android.com/tools/support-library/features.html#v4">v4 support
+library</a> and the Developer Preview support library. So to get started,
+you should include the following imports in your project code:</p>
+
+<pre>
+import android.preview.support.wearable.notifications.*;
+import android.preview.support.v4.app.NotificationManagerCompat;
+import android.support.v4.app.NotificationCompat;
+</pre>
+
+<p class="caution"><strong>Caution:</strong>
+The APIs in the current Android Wear Developer Preview are intended for <b>development and testing purposes only</b>, not for production apps. Google may change this Developer Preview significantly prior to the official release of the Android Wear SDK. You may not publicly distribute or ship any application using this Developer Preview, as this Developer Preview will no longer be supported after the official SDK is released (which will cause applications based only on the Developer Preview to break).</p>
+
+
+
+<h2 id="NotificationBuilder">Create Notifications with the Notification Builder</h2>
+
+<p>The <a href="http://developer.android.com/tools/support-library/features.html#v4">v4
+support library</a> allows you to create notifications using the latest notification features
+such as action buttons and large icons, while remaining compatible with Android 1.6 (API level
+4) and higher.</p>
+
+
+<p>For example, here's some code that creates and issues a notification using the
+{@link android.support.v4.app.NotificationCompat} APIs combined with the new
+<a href="{@docRoot}reference/android/preview/support/v4/app/NotificationManagerCompat.html">
+<code>NotificationManagerCompat</code></a> API:</p>
+
+
+<pre>
+int notificationId = 001;
+// Build intent for notification content
+Intent viewIntent = new Intent(this, ViewEventActivity.class);
+viewIntent.putExtra(EXTRA_EVENT_ID, eventId);
+PendingIntent viewPendingIntent =
+ PendingIntent.getActivity(this, 0, viewIntent, 0);
+
+NotificationCompat.Builder notificationBuilder =
+ new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.ic_event)
+ .setContentTitle(eventTitle)
+ .setContentText(eventLocation)
+ .setContentIntent(viewPendingIntent);
+
+// Get an instance of the NotificationManager service
+NotificationManagerCompat notificationManager =
+ NotificationManagerCompat.from(this);
+
+// Build the notification and issues it with notification manager.
+notificationManager.notify(notificationId, notificationBuilder.build());
+</pre>
+
+<p>When this notification appears on a handheld device, the user can invoke the
+{@link android.app.PendingIntent}
+specified by the {@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+setContentIntent()} method by touching the notification. When this
+notification appears on an Android wearable, the user can swipe the notification to the left to
+reveal the <strong>Open</strong> action, which invokes the intent on the handheld device.</p>
+
+
+
+
+
+
+<img src="{@docRoot}wear/images/circle_email_action.png" height="200" style="float:right;clear:right;margin:0 0 20px 60px" />
+
+<h2 id="ActionButtons">Add Action Buttons</h2>
+
+<p>In addition to the primary content action defined by
+{@link android.support.v4.app.NotificationCompat.Builder#setContentIntent
+setContentIntent()}, you can add other actions by passing a {@link android.app.PendingIntent} to
+the {@link android.support.v4.app.NotificationCompat.Builder#addAction
+addAction()} method.</p>
+
+<p>For example, the following code shows the same type of notification from above, but adds an
+action to view the event location on a map.</p>
+
+<pre style="clear:right">
+// Build an intent for an action to view a map
+Intent mapIntent = new Intent(Intent.ACTION_VIEW);
+Uri geoUri = Uri.parse("geo:0,0?q=" + Uri.encode(location));
+mapIntent.setData(geoUri);
+PendingIntent mapPendingIntent =
+ PendingIntent.getActivity(this, 0, mapIntent, 0);
+
+NotificationCompat.Builder notificationBuilder =
+ new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.ic_event)
+ .setContentTitle(eventTitle)
+ .setContentText(eventLocation)
+ .setContentIntent(viewPendingIntent)
+ <b>.addAction(R.drawable.ic_map,
+ getString(R.string.map), mapPendingIntent);</b>
+</pre>
+
+<p>On a handheld device, the action appears as an
+additional button attached to the notification. On an Android wearable, the action appears as
+a large button when the user swipes the notification to the left. When the user taps the action,
+the associated {@link android.content.Intent} is invoked on the handheld device.</p>
+
+<p class="note"><strong>Tip:</strong> If your notifications includes a "Reply" action
+ (such as for a messaging app), you can enhance the behavior by enabling
+ voice input replies directly from the Android wearable. For more information, read
+ <a href="{@docRoot}wear/notifications/remote-input.html">Receiving Voice Input from a Notification</a>.
+</p>
+
+<p>For details about designing action buttons (including the icon specifications), see the
+<a href="{@docRoot}wear/design/index.html#NotifictionActions">Design Principles of Android
+Wear</a>.</p>
+
+
+<h2 id="BigView">Add a Big View</h2>
+
+<img src="{@docRoot}wear/images/06_images.png" height="200" style="float:right;margin:0 0 20px 40px" />
+
+<p>You can insert extended text content
+to your notification by adding one of the "big view" styles to your notification. On a
+handheld device, users can see the big view content by expanding the notification,
+while on Android Wear, the big view content is visible by default.</p>
+
+<p>To add the extended content to your notification, call {@link
+android.support.v4.app.NotificationCompat.Builder#setStyle setStyle()} on the {@link
+android.support.v4.app.NotificationCompat.Builder} object, passing it an instance of either
+{@link android.support.v4.app.NotificationCompat.BigTextStyle BigTextStyle} or
+{@link android.support.v4.app.NotificationCompat.InboxStyle InboxStyle}.</p>
+
+<p>For example, the following code adds an instance of
+{@link android.support.v4.app.NotificationCompat.BigTextStyle} to the event notification,
+in order to include the complete event description (which includes more text than can fit
+into the space provided for {@link android.support.v4.app.NotificationCompat.Builder#setContentText
+setContentText()}).</p>
+
+
+<pre style="clear:right">
+// Specify the 'big view' content to display the long
+// event description that may not fit the normal content text.
+BigTextStyle bigStyle = new NotificationCompat.BigTextStyle();
+bigStyle.bigText(eventDescription);
+
+NotificationCompat.Builder notificationBuilder =
+ new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.ic_event)
+ .setLargeIcon(BitmapFractory.decodeResource(
+ getResources(), R.drawable.notif_background))
+ .setContentTitle(eventTitle)
+ .setContentText(eventLocation)
+ .setContentIntent(viewPendingIntent)
+ .addAction(R.drawable.ic_map,
+ getString(R.string.map), mapPendingIntent)
+ <b>.setStyle(bigStyle);</b>
+</pre>
+
+<p>Notice that you can add a large background image to any notification using the
+{@link android.support.v4.app.NotificationCompat.Builder#setLargeIcon setLargeIcon()}
+method. For more information about designing notifications with large images, see the
+<a href="{@docRoot}wear/design/index.html#Images">Design Principles of Android
+Wear</a>.</p>
+
+
+
+<h2 id="NewFeatures">Add New Features for Wearables</h2>
+
+<p>The Android Wear preview support library provides new APIs that
+ allow you to enhance the user experience for notifications on a wearable device. For example,
+ you can add additional pages of content that users can view by swiping to the left, or add the ability
+for users to deliver your app a text response using voice input.</p>
+
+<p>To use these new APIs, pass your instance of
+{@link android.support.v4.app.NotificationCompat.Builder} to the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#WearableNotifications.Builder(android.content.Context)"> <code>WearableNotifications.Builder()</code></a> constructor. You can then add new
+features to your notification using the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"
+ ><code>WearableNotifications.Builder</code></a> methods. For example:</p>
+
+<pre>
+// Create a NotificationCompat.Builder for standard notification features
+NotificationCompat.Builder notificationBuilder =
+ new NotificationCompat.Builder(mContext)
+ .setContentTitle("New mail from " + sender.toString())
+ .setContentText(subject)
+ .setSmallIcon(R.drawable.new_mail);
+
+// Create a WearablesNotification.Builder to add special functionality for wearables
+Notification notification =
+ new WearableNotifications.Builder(notificationBuilder)
+ .setHintHideIcon(true)
+ .build();
+</pre>
+
+<p>The <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setBigActionIcon(int)">
+ <code>setHintHideIcon()</code></a> method removes your app icon from the notification card.
+ This method is just one example of new notification features available from the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"
+ ><code>WearableNotifications.Builder</code></a> class.</p>
+
+<p>When you want to deliver your notifications, be certain to always use the
+ <a href="{@docRoot}reference/android/preview/support/v4/app/NotificationManagerCompat.html">
+ <code>NotificationManagerCompat</code></a> API:</p>
+
+<pre>
+// Get an instance of the NotificationManager service
+NotificationManagerCompat notificationManager =
+ NotificationManagerCompat.from(this);
+
+// Build the notification and issues it with notification manager.
+notificationManager.notify(notificationId, notification);
+</pre>
+
+<p>If you instead use the framework's {@link android.app.NotificationManager}, some
+features from <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"><code>WearableNotifications.Builder</code></a>
+will not work.</p>
+
+<p>To continue enhancing your notifications for wearables using
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"
+ ><code>WearableNotifications.Builder</code></a> and other APIs in the
+ preview support library, see the following developer guides:</p>
+
+ <dl>
+ <dt><a href="{@docRoot}wear/notifications/remote-input.html">Receiving Voice Input
+from a Notification</a></dt>
+ <dd>Add an action that receives voice input from the user and delivers the
+transcribed message to your app.</dd>
+ <dt><a href="{@docRoot}wear/notifications/pages.html">Adding Pages to a Notification</a></dt>
+ <dd>Add additional pages of information that are visible when the user
+swipes to the left.</dd>
+ <dt><a href="{@docRoot}wear/notifications/stacks.html">Stacking Notifications</a></dt>
+ <dd>Place all similar notifications from your app in a stack, allowing each to be
+viewed individually without adding multiple cards to the card stream.</dd>
+ </dl>
+
+
+<div class="next-docs">
+
+<div class="col-12">
+ <h2 class="norule">You might also want to read:</h2>
+ <dl>
+ <dt><a href="{@docRoot}training/notify-user/index.html">Notifying the User</a></dt>
+ <dd>Learn more about how to create notifications.</dd>
+ <dt><a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a></dt>
+ <dd>Learn everything you need to know about the {@link android.content.Intent}
+APIs, used by notificaton actions.</dd>
+ </dl>
+</div>
+</div>
+
+
+</body>
+</html>
diff --git a/docs/html/wear/notifications/pages.html b/docs/html/wear/notifications/pages.html
deleted file mode 100644
index ce568eb..0000000
--- a/docs/html/wear/notifications/pages.html
+++ /dev/null
@@ -1,500 +0,0 @@
-<!DOCTYPE html>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Adding Pages to a Notification | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display"> </div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Adding Pages to a Notification</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <img src="/wear/images/09_pages.png" height="200" style="float:right;margin:0 0 20px 40px" />
-<img src="/wear/images/08_pages.png" height="200" style="float:right;margin:0 0 20px 40px" />
-
-<p>When you'd like to provide more information without requiring users
-to open your app on their handheld device, you can
-add one or more pages to the notification on Android Wear. The additional pages
-appear immediately to the right of the main notification card.
-For information about when to use and how to design
-multiple pages, see the
-<a href="/wear/design/index.html#NotificationPages">Design Principles of Android
-Wear</a>.</p>
-
-
-<p>When creating a notification with multiple pages, start by creating the main notification
-(the first page) the way you'd like the notification to appear on a phone
-or tablet. Then, add pages one at a time with the
-<a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addPage(android.app.Notification)">
-<code>addPage()</code></a> method, or add multiple pages in a <code><a href="/reference/java/util/Collection.html">Collection</a></code> with the
-<a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addPages(java.util.Collection<android.app.Notification>)">
-<code>addPages()</code></a> method.</p>
-
-
-<p>For example, here's some code that adds a second page to a notification:</p>
-
-<pre>
-// Create builder for the main notification
-NotificationCompat.Builder notificationBuilder =
- new NotificationCompat.Builder(this)
- .setSmallIcon(R.drawable.new_message)
- .setContentTitle("Page 1")
- .setContentText("Short message")
- .setContentIntent(viewPendingIntent);
-
-// Create a big text style for the second page
-BigTextStyle secondPageStyle = new NotificationCompat.BigTextStyle();
-secondPageStyle.setBigContentTitle("Page 2")
- .bigText("A lot of text...");
-
-// Create second page notification
-Notification secondPageNotification =
- new NotificationCompat.Builder(this)
- .setStyle(secondPageStyle)
- .build();
-
-// Create main notification and add the second page
-Notification twoPageNotification =
- new WearableNotifications.Builder(notificationBuilder)
- .addPage(secondPageNotification)
- .build();
-</pre>
-
-
-
-
-</body>
-</html>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a> |
- <a href="/legal.html">Legal</a> |
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/notifications/pages.jd b/docs/html/wear/notifications/pages.jd
new file mode 100644
index 0000000..558f7b8
--- /dev/null
+++ b/docs/html/wear/notifications/pages.jd
@@ -0,0 +1,61 @@
+page.title=Adding Pages to a Notification
+
+@jd:body
+
+
+<img src="{@docRoot}wear/images/09_pages.png" height="200" style="float:right;margin:0 0 20px 40px" />
+<img src="{@docRoot}wear/images/08_pages.png" height="200" style="float:right;margin:0 0 20px 40px" />
+
+<p>When you'd like to provide more information without requiring users
+to open your app on their handheld device, you can
+add one or more pages to the notification on Android Wear. The additional pages
+appear immediately to the right of the main notification card.
+For information about when to use and how to design
+multiple pages, see the
+<a href="{@docRoot}wear/design/index.html#NotificationPages">Design Principles of Android
+Wear</a>.</p>
+
+
+<p>When creating a notification with multiple pages, start by creating the main notification
+(the first page) the way you'd like the notification to appear on a phone
+or tablet. Then, add pages one at a time with the
+<a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addPage(android.app.Notification)">
+<code>addPage()</code></a> method, or add multiple pages in a {@link java.util.Collection} with the
+<a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addPages(java.util.Collection<android.app.Notification>)">
+<code>addPages()</code></a> method.</p>
+
+
+<p>For example, here's some code that adds a second page to a notification:</p>
+
+<pre>
+// Create builder for the main notification
+NotificationCompat.Builder notificationBuilder =
+ new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.new_message)
+ .setContentTitle("Page 1")
+ .setContentText("Short message")
+ .setContentIntent(viewPendingIntent);
+
+// Create a big text style for the second page
+BigTextStyle secondPageStyle = new NotificationCompat.BigTextStyle();
+secondPageStyle.setBigContentTitle("Page 2")
+ .bigText("A lot of text...");
+
+// Create second page notification
+Notification secondPageNotification =
+ new NotificationCompat.Builder(this)
+ .setStyle(secondPageStyle)
+ .build();
+
+// Create main notification and add the second page
+Notification twoPageNotification =
+ new WearableNotifications.Builder(notificationBuilder)
+ .addPage(secondPageNotification)
+ .build();
+</pre>
+
+
+
+
+</body>
+</html>
diff --git a/docs/html/wear/notifications/remote-input.html b/docs/html/wear/notifications/remote-input.html
deleted file mode 100644
index c8f6621..0000000
--- a/docs/html/wear/notifications/remote-input.html
+++ /dev/null
@@ -1,652 +0,0 @@
-<!DOCTYPE html>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Receiving Voice Input from a Notification | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display"> </div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Receiving Voice Input from a Notification</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <img src="/wear/images/13_voicereply.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
-
-<img src="/wear/images/03_actions.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
-
-<p>If your notification includes an action to respond with text,
- such as to reply to an email, it should normally launch an activity
- on the handheld device. However, when your notification appears on an Android wearable, you can
- allow users to dictate a reply with voice input. You can also provide pre-defined text
- messages for the user to select.</p>
-
-<p>When the user replies with voice or selects one of the available
-messages, the system sends the message to your app on the connected handheld device.
-The message is attached as an extra in the <code><a href="/reference/android/content/Intent.html">Intent</a></code> you specified
-to be used for the notification action.</p>
-
-<p class="note"><strong>Note:</strong> When developing with the Android emulator,
-you must type text replies into the voice input field, so be sure you have enabled
-<strong>Hardware keyboard present</strong> in the AVD settings.</p>
-
-
-<h2 id="RemoteInput">Define the Remote Input</h2>
-
-<p>To create an action that supports voice input, first create an instance of
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">
-<code>RemoteInput</code></a> using the
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html"><code>RemoteInput.Builder</code></a> APIs.
- The
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html"><code>RemoteInput.Builder</code></a> constructor takes a string that the system
- will use as a key for the <code><a href="/reference/android/content/Intent.html">Intent</a></code> extra that carries the reply message
- to your app on the handheld.</p>
-
-<p>For example, here's how to create a new
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">
-<code>RemoteInput</code></a> object that provides a custom
- label for the voice input prompt:</p>
-
-<pre class="prettyprint">
-// Key for the string that's delivered in the action's intent
-private static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
-
-String replyLabel = getResources().getString(R.string.reply_label);
-
-RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
- .setLabel(replyLabel)
- .build();
-</pre>
-
-
-<h3>Add Pre-defined Text Responses</h3>
-
-<img src="/wear/images/12_voicereply.png" height="200" style="float:right;margin:0 0 20px 40px" />
-
-<p>In addition to allowing voice input, you can
- provide up to five text responses that the user can select for quick replies. Call
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html#setChoices(java.lang.String[])"><code>setChoices()</code></a> and pass it a string array.</p>
-
-<p>For example, you may define some responses in a resource array:</p>
-
-<p class="code-caption">res/values/strings.xml</code>
-<pre class="prettyprint">
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string-array name="reply_choices">
- <item>Yes</item>
- <item>No</item>
- <item>Maybe</item>
- </string-array>
-</resources>
-</pre>
-
-<p>Then, inflate the string array and add it to the
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a>:</p>
-
-<pre>
-String replyLabel = getResources().getString(R.string.reply_label);
-String[] replyChoices = getResources().getStringArray(R.array.reply_choices);
-
-RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
- .setLabel(replyLabel)
- .setChoices(replyChoices)
- .build();
-</pre>
-
-
-
-
-<h2 id="PrimaryAction">Receive Voice Input for the Primary Action</h2>
-
-<p>If "Reply" is your notification's primary action (defined by the <code><a href="/reference/android/support/v4/app/NotificationCompat.Builder.html#setContentIntent(android.app.PendingIntent)">setContentIntent()</a></code>
-method), then you should attach the
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to the main action using
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addRemoteInputForContentIntent(android.preview.support.wearable.notifications.RemoteInput)">
-<code>addRemoteInputForContentIntent()</code></a>. For example:</p>
-
-<pre>
-// Create intent for reply action
-Intent replyIntent = new Intent(this, ReplyActivity.class);
-PendingIntent replyPendingIntent =
- PendingIntent.getActivity(this, 0, replyIntent, 0);
-
-// Build the notification
-NotificationCompat.Builder replyNotificationBuilder =
- new NotificationCompat.Builder(this)
- .setSmallIcon(R.drawable.ic_new_message)
- .setContentTitle("Message from Travis")
- .setContentText("I love key lime pie!")
- .setContentIntent(replyPendingIntent);
-
-// Create the remote input
-RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
- .setLabel(replyLabel)
- .build();
-
-// Create wearable notification and add remote input
-Notification replyNotification =
- new WearableNotifications.Builder(replyNotificationBuilder)
- .addRemoteInputForContentIntent(replyAction)
- .build();
-</pre>
-
-
-<p>By using
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addRemoteInputForContentIntent(android.preview.support.wearable.notifications.RemoteInput)">
-<code>addRemoteInputForContentIntent()</code></a> to add the
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> object to the notification's primary action,
-the button that normally appears as an "Open" action becomes the "Reply" action
-and starts the voice input UI when users select it on Android Wear.</p>
-
-
-
-<h2 id="NewAction">Receive Voice Input for a Secondary Action</h2>
-
-<p>If the "Reply" action is not your notification's primary action and you want to enable
-voice input for a secondary action, add the
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to a new action button defined by an
- <a href="/reference/android/preview/support/wearable/notifications/Action.html">
-<code>Action</code></a> object.</p>
-
-<p>You should instantiate the
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">
-<code>Action</code></a> with the
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html"><code>Action.Builder()</code></a>
-constructor, which takes an icon and text label for the action button, plus the
-<code><a href="/reference/android/app/PendingIntent.html">PendingIntent</a></code>
-the system should use to invoke your app when the user selects the action. For example:</p>
-
-<pre>
-// Create the pending intent to fire when the user selects the action
-Intent replyIntent = new Intent(this, ReplyActivity.class);
-PendingIntent pendingReplyIntent =
- PendingIntent.getActivity(this, 0, replyIntent, 0);
-
-// Create the remote input
-RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
- .setLabel(replyLabel)
- .build();
-
-// Create the notification action
-Action replyAction = new Action.Builder(R.drawable.ic_message,
- "Reply", pendingIntent)
- .addRemoteInput(remoteInput)
- .build();
-</pre>
-
-
-<p>After you add the
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to the
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">
-<code>Action</code></a>, add the
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">
-<code>Action</code></a> to the
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"><code>WearableNotifications.Builder</code></a> using
- <a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addAction(Action)"><code>addAction()</code></a>.
-For example:</p>
-
-<pre>
-// Create basic notification builder
-NotificationCompat.Builder replyNotificationBuilder =
- new NotificationCompat.Builder(this)
- .setContentTitle("New message");
-
-// Create the notification action and add remote input
-Action replyAction = new Action.Builder(R.drawable.ic_message,
- "Reply", pendingIntent)
- .addRemoteInput(remoteInput)
- .build();
-
-// Create wearable notification and add action
-Notification replyNotification =
- new WearableNotifications.Builder(replyNotificationBuilder)
- .addAction(replyAction)
- .build();
-</pre>
-
-<p>Now, when the user selects "Reply" from an Android wearable, the system prompts the user
- for voice input (and shows the list of pre-defined replies, if provided).
- Once the user completes a response, the system invokes
- the <code><a href="/reference/android/content/Intent.html">Intent</a></code> attached to the action and adds the
-<code>EXTRA_VOICE_REPLY</code> extra (the string
- you passed to the
- <a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html"><code>RemoteInput.Builder</code></a> constructor)
- with the user's message as the string value.</p>
-
-
-
-
-</body>
-</html>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a> |
- <a href="/legal.html">Legal</a> |
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/notifications/remote-input.jd b/docs/html/wear/notifications/remote-input.jd
new file mode 100644
index 0000000..1668363
--- /dev/null
+++ b/docs/html/wear/notifications/remote-input.jd
@@ -0,0 +1,213 @@
+page.title=Receiving Voice Input from a Notification
+
+@jd:body
+
+<img src="{@docRoot}wear/images/13_voicereply.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
+
+<img src="{@docRoot}wear/images/03_actions.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
+
+<p>If your notification includes an action to respond with text,
+ such as to reply to an email, it should normally launch an activity
+ on the handheld device. However, when your notification appears on an Android wearable, you can
+ allow users to dictate a reply with voice input. You can also provide pre-defined text
+ messages for the user to select.</p>
+
+<p>When the user replies with voice or selects one of the available
+messages, the system sends the message to your app on the connected handheld device.
+The message is attached as an extra in the {@link android.content.Intent} you specified
+to be used for the notification action.</p>
+
+<p class="note"><strong>Note:</strong> When developing with the Android emulator,
+you must type text replies into the voice input field, so be sure you have enabled
+<strong>Hardware keyboard present</strong> in the AVD settings.</p>
+
+
+<h2 id="RemoteInput">Define the Remote Input</h2>
+
+<p>To create an action that supports voice input, first create an instance of
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.html">
+<code>RemoteInput</code></a> using the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html"><code>RemoteInput.Builder</code></a> APIs.
+ The
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html"><code>RemoteInput.Builder</code></a> constructor takes a string that the system
+ will use as a key for the {@link android.content.Intent} extra that carries the reply message
+ to your app on the handheld.</p>
+
+<p>For example, here's how to create a new
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.html">
+<code>RemoteInput</code></a> object that provides a custom
+ label for the voice input prompt:</p>
+
+<pre class="prettyprint">
+// Key for the string that's delivered in the action's intent
+private static final String EXTRA_VOICE_REPLY = "extra_voice_reply";
+
+String replyLabel = getResources().getString(R.string.reply_label);
+
+RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
+ .setLabel(replyLabel)
+ .build();
+</pre>
+
+
+<h3>Add Pre-defined Text Responses</h3>
+
+<img src="{@docRoot}wear/images/12_voicereply.png" height="200" style="float:right;margin:0 0 20px 40px" />
+
+<p>In addition to allowing voice input, you can
+ provide up to five text responses that the user can select for quick replies. Call
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html#setChoices(java.lang.String[])"><code>setChoices()</code></a> and pass it a string array.</p>
+
+<p>For example, you may define some responses in a resource array:</p>
+
+<p class="code-caption">res/values/strings.xml</code>
+<pre class="prettyprint">
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string-array name="reply_choices">
+ <item>Yes</item>
+ <item>No</item>
+ <item>Maybe</item>
+ </string-array>
+</resources>
+</pre>
+
+<p>Then, inflate the string array and add it to the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a>:</p>
+
+<pre>
+String replyLabel = getResources().getString(R.string.reply_label);
+String[] replyChoices = getResources().getStringArray(R.array.reply_choices);
+
+RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
+ .setLabel(replyLabel)
+ .setChoices(replyChoices)
+ .build();
+</pre>
+
+
+
+
+<h2 id="PrimaryAction">Receive Voice Input for the Primary Action</h2>
+
+<p>If "Reply" is your notification's primary action (defined by the {@link
+android.support.v4.app.NotificationCompat.Builder#setContentIntent setContentIntent()}
+method), then you should attach the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to the main action using
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addRemoteInputForContentIntent(android.preview.support.wearable.notifications.RemoteInput)">
+<code>addRemoteInputForContentIntent()</code></a>. For example:</p>
+
+<pre>
+// Create intent for reply action
+Intent replyIntent = new Intent(this, ReplyActivity.class);
+PendingIntent replyPendingIntent =
+ PendingIntent.getActivity(this, 0, replyIntent, 0);
+
+// Build the notification
+NotificationCompat.Builder replyNotificationBuilder =
+ new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.ic_new_message)
+ .setContentTitle("Message from Travis")
+ .setContentText("I love key lime pie!")
+ .setContentIntent(replyPendingIntent);
+
+// Create the remote input
+RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
+ .setLabel(replyLabel)
+ .build();
+
+// Create wearable notification and add remote input
+Notification replyNotification =
+ new WearableNotifications.Builder(replyNotificationBuilder)
+ .addRemoteInputForContentIntent(remoteInput)
+ .build();
+</pre>
+
+
+<p>By using
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addRemoteInputForContentIntent(android.preview.support.wearable.notifications.RemoteInput)">
+<code>addRemoteInputForContentIntent()</code></a> to add the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> object to the notification's primary action,
+the button that normally appears as an "Open" action becomes the "Reply" action
+and starts the voice input UI when users select it on Android Wear.</p>
+
+
+
+<h2 id="NewAction">Receive Voice Input for a Secondary Action</h2>
+
+<p>If the "Reply" action is not your notification's primary action and you want to enable
+voice input for a secondary action, add the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to a new action button defined by an
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">
+<code>Action</code></a> object.</p>
+
+<p>You should instantiate the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">
+<code>Action</code></a> with the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html"><code>Action.Builder()</code></a>
+constructor, which takes an icon and text label for the action button, plus the
+{@link android.app.PendingIntent}
+the system should use to invoke your app when the user selects the action. For example:</p>
+
+<pre>
+// Create the pending intent to fire when the user selects the action
+Intent replyIntent = new Intent(this, ReplyActivity.class);
+PendingIntent pendingReplyIntent =
+ PendingIntent.getActivity(this, 0, replyIntent, 0);
+
+// Create the remote input
+RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)
+ .setLabel(replyLabel)
+ .build();
+
+// Create the notification action
+Action replyAction = new Action.Builder(R.drawable.ic_message,
+ "Reply", pendingIntent)
+ .addRemoteInput(remoteInput)
+ .build();
+</pre>
+
+
+<p>After you add the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.html"><code>RemoteInput</code></a> to the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">
+<code>Action</code></a>, add the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">
+<code>Action</code></a> to the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html"><code>WearableNotifications.Builder</code></a> using
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#addAction(Action)"><code>addAction()</code></a>.
+For example:</p>
+
+<pre>
+// Create basic notification builder
+NotificationCompat.Builder replyNotificationBuilder =
+ new NotificationCompat.Builder(this)
+ .setContentTitle("New message");
+
+// Create the notification action and add remote input
+Action replyAction = new Action.Builder(R.drawable.ic_message,
+ "Reply", pendingIntent)
+ .addRemoteInput(remoteInput)
+ .build();
+
+// Create wearable notification and add action
+Notification replyNotification =
+ new WearableNotifications.Builder(replyNotificationBuilder)
+ .addAction(replyAction)
+ .build();
+</pre>
+
+<p>Now, when the user selects "Reply" from an Android wearable, the system prompts the user
+ for voice input (and shows the list of pre-defined replies, if provided).
+ Once the user completes a response, the system invokes
+ the {@link android.content.Intent} attached to the action and adds the
+<code>EXTRA_VOICE_REPLY</code> extra (the string
+ you passed to the
+ <a href="{@docRoot}reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html"><code>RemoteInput.Builder</code></a> constructor)
+ with the user's message as the string value.</p>
+
+
+
+
+</body>
+</html>
diff --git a/docs/html/wear/notifications/stacks.html b/docs/html/wear/notifications/stacks.html
deleted file mode 100644
index e4f74a0..0000000
--- a/docs/html/wear/notifications/stacks.html
+++ /dev/null
@@ -1,512 +0,0 @@
-<!DOCTYPE html>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Stacking Notifications | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display"> </div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Stacking Notifications</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <img src="/wear/images/11_bundles_B.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
-<img src="/wear/images/11_bundles_A.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
-
-<p>When creating notifications for a handheld device, you should always aggregate similar
-notifications into a single summary notification. For example, if your app creates notifications
-for received messages, you should not show more than one notification
-on a handheld device—when more than one is message is received, use a single notification
-to provide a summary such as "2 new messages."</p>
-
-<p>However, a summary notification is less useful on an Android wearable because users
-are not able to read details from each message on the wearable (they must open your app on the
-handheld to view more information). So for the wearable device, you should
-group all the notifications together in a stack. The stack of notifications appears as a single
-card, which users can expand to view the details from each notification separately. The new
-<a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setGroup(java.lang.String, int)">
-<code>setGroup()</code></a> method makes this possible while allowing you to still provide
-only one summary notification on the handheld device.</p>
-
-<p>For details about designing notification stacks, see the
-<a href="/wear/design/index.html#NotificationStacks">Design Principles of Android
-Wear</a>.</p>
-
-
-<h2 id="AddGroup">Add Each Notification to a Group</h2>
-
-<p>To create a stack, call <a
-href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setGroup(java.lang.String, int)">
-<code>setGroup()</code></a> for each notification you want in the stack, passing the same
-group key. For example:</p>
-
-<pre style="clear:right">
-final static String GROUP_KEY_EMAILS = "group_key_emails";
-
-NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext)
- .setContentTitle("New mail from " + sender)
- .setContentText(subject)
- .setSmallIcon(R.drawable.new_mail);
-
-Notification notif = new WearableNotifications.Builder(builder)
- .setGroup(GROUP_KEY_EMAILS)
- .build();
-</pre>
-
-<p>By default, notifications appear in the order in which you added them, with the most recent
- notification visible at the top. You can define a specific position in the group
- by passing an order position as the second parameter for <a
-href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setGroup(java.lang.String, int)">
-<code>setGroup()</code></a>.</p>
-
-
-<h2 id="AddSummary">Add a Summary Notification</h2>
-
-<p>It's important that you still provide a summary notification that appears on handheld devices.
-So in addition to adding each unique notification to the same stack group, also add a summary
-notification, but set its order position to be <a
-href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html#GROUP_ORDER_SUMMARY"><code>GROUP_ORDER_SUMMARY</code></a>.</p>
-
-<pre>
-Notification summaryNotification = new WearableNotifications.Builder(builder)
- .setGroup(GROUP_KEY_EMAILS, WearableNotifications.GROUP_ORDER_SUMMARY)
- .build();
-</pre>
-
-<p>This notification will not appear in your stack of notifications on the wearable, but
-appears as the only notification on the handheld device.
-
-</body>
-</html>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a> |
- <a href="/legal.html">Legal</a> |
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/notifications/stacks.jd b/docs/html/wear/notifications/stacks.jd
new file mode 100644
index 0000000..7f955f6
--- /dev/null
+++ b/docs/html/wear/notifications/stacks.jd
@@ -0,0 +1,72 @@
+page.title=Stacking Notifications
+
+@jd:body
+
+<img src="{@docRoot}wear/images/11_bundles_B.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
+<img src="{@docRoot}wear/images/11_bundles_A.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
+
+<p>When creating notifications for a handheld device, you should always aggregate similar
+notifications into a single summary notification. For example, if your app creates notifications
+for received messages, you should not show more than one notification
+on a handheld device—when more than one is message is received, use a single notification
+to provide a summary such as "2 new messages."</p>
+
+<p>However, a summary notification is less useful on an Android wearable because users
+are not able to read details from each message on the wearable (they must open your app on the
+handheld to view more information). So for the wearable device, you should
+group all the notifications together in a stack. The stack of notifications appears as a single
+card, which users can expand to view the details from each notification separately. The new
+<a href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setGroup(java.lang.String, int)">
+<code>setGroup()</code></a> method makes this possible while allowing you to still provide
+only one summary notification on the handheld device.</p>
+
+<p>For details about designing notification stacks, see the
+<a href="{@docRoot}wear/design/index.html#NotificationStacks">Design Principles of Android
+Wear</a>.</p>
+
+
+<h2 id="AddGroup">Add Each Notification to a Group</h2>
+
+<p>To create a stack, call <a
+href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setGroup(java.lang.String, int)">
+<code>setGroup()</code></a> for each notification you want in the stack, passing the same
+group key. For example:</p>
+
+<pre style="clear:right">
+final static String GROUP_KEY_EMAILS = "group_key_emails";
+
+NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext)
+ .setContentTitle("New mail from " + sender)
+ .setContentText(subject)
+ .setSmallIcon(R.drawable.new_mail);
+
+Notification notif = new WearableNotifications.Builder(builder)
+ .setGroup(GROUP_KEY_EMAILS)
+ .build();
+</pre>
+
+<p>By default, notifications appear in the order in which you added them, with the most recent
+ notification visible at the top. You can define a specific position in the group
+ by passing an order position as the second parameter for <a
+href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setGroup(java.lang.String, int)">
+<code>setGroup()</code></a>.</p>
+
+
+<h2 id="AddSummary">Add a Summary Notification</h2>
+
+<p>It's important that you still provide a summary notification that appears on handheld devices.
+So in addition to adding each unique notification to the same stack group, also add a summary
+notification, but set its order position to be <a
+href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.html#GROUP_ORDER_SUMMARY"><code>GROUP_ORDER_SUMMARY</code></a>.</p>
+
+<pre>
+Notification summaryNotification = new WearableNotifications.Builder(builder)
+ .setGroup(GROUP_KEY_EMAILS, WearableNotifications.GROUP_ORDER_SUMMARY)
+ .build();
+</pre>
+
+<p>This notification will not appear in your stack of notifications on the wearable, but
+appears as the only notification on the handheld device.
+
+</body>
+</html>
diff --git a/docs/html/wear/preview/signup.html b/docs/html/wear/preview/signup.jd
similarity index 64%
rename from docs/html/wear/preview/signup.html
rename to docs/html/wear/preview/signup.jd
index ca50179..8e8ec9a 100644
--- a/docs/html/wear/preview/signup.html
+++ b/docs/html/wear/preview/signup.jd
@@ -1,379 +1,8 @@
-<!DOCTYPE html>
+page.title=Sign Up for the Developer Preview
+@jd:body
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Sign Up for the Developer Preview | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display"> </div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Sign Up for the Developer Preview</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <p>To get started with the Android Wear Developer Preview, you must agree to the
+<p>To get started with the Android Wear Developer Preview, you must agree to the
following terms and conditions and provide the email address for your Google account.
After signing up, you’ll have access to:</p>
<ul>
@@ -538,72 +167,3 @@
</body>
</html>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a> |
- <a href="/legal.html">Legal</a> |
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/preview/start.html b/docs/html/wear/preview/start.html
deleted file mode 100644
index 4aec648..0000000
--- a/docs/html/wear/preview/start.html
+++ /dev/null
@@ -1,690 +0,0 @@
-<!DOCTYPE html>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<html>
-<head>
-
-
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-<meta name="viewport" content="width=device-width" />
-
-<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
-<title>Get Started with the Developer Preview | Android Developers</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="//fonts.googleapis.com/css?family=Roboto:light,regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="/assets/css/default.css" rel="stylesheet" type="text/css">
-
-
-
-<!-- JAVASCRIPT -->
-<script src="//www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/js/android_3p-bundle.js" type="text/javascript"></script>
-<script type="text/javascript">
- var toRoot = "/";
- var metaTags = [];
- var devsite = false;
-</script>
-<script src="/assets/js/docs.js" type="text/javascript"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-5831155-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
-
-<body class="gc-documentation
- " itemscope itemtype="http://schema.org/Article">
-
-
-
-<a name="top"></a>
-
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo-wear">
- <a href="/wear/index.html">
- <img src="/wear/images/android-wear.png" height="16" alt="Android Wear" />
- </a>
- </div>
-
-
- <div class="col-8" style="margin:0"><h1 style="margin:1px 0 0 20px;padding:0;line-height:16px;
- color:#666;font-weight:100;font-size:24px;">Developer Preview</h1></div>
-
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="/about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-
-
- <div class="header">Language</div>
- <div id="language" class="locales">
- <select name="language" onChange="changeLangPref(this.value, true)">
- <option value="en">English</option>
- <option value="es">Español</option>
- <option value="ja">日本語</option>
- <option value="ko">한국어</option>
- <option value="ru">Русский</option>
- <option value="zh-cn">中文 (中国)</option>
- <option value="zh-tw">中文 (台灣)</option>
- </select>
- </div>
- <script type="text/javascript">
- <!--
- loadLangPref();
- //-->
- </script>
-
-
-
-
- <br class="clearfix" />
- </div><!-- end mid -->
- <div class="bottom"></div>
- </div><!-- end morehover -->
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '/')"
-onkeyup="return search_changed(event, false, '/')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div><!-- end search -->
-
- <div class="search_filtered_wrapper reference">
- <div class="suggest-card reference no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div>
-
- <div class="search_filtered_wrapper docs">
- <div class="suggest-card dummy no-display"> </div>
- <div class="suggest-card develop no-display">
- <ul class="search_filtered">
- </ul>
- <div class="child-card guides no-display">
- </div>
- <div class="child-card training no-display">
- </div>
- <div class="child-card samples no-display">
- </div>
- </div>
- <div class="suggest-card design no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- <div class="suggest-card distribute no-display">
- <ul class="search_filtered">
- </ul>
- </div>
- </div><!-- end search_filtered_wrapper -->
-
- </div>
- <!-- end menu_container -->
-
-
- </div><!-- end header-wrap -->
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-
-
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<ul id="nav">
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/preview/start.html">Get Started
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/user-interface.html">UI Overview
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/design/index.html">Design Principles
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/creating.html">Creating Notifications for Android Wear
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/remote-input.html">Receiving Voice Input from a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/pages.html">Adding Pages to a Notification
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/notifications/stacks.html">Stacking Notifications
- </a></div>
- </li>
-
- <li class="nav-section">
- <div class="nav-section-header"><a href="/reference/android/preview/support/package-summary.html">Notification Reference</a></div>
- <ul class="tree-list-children">
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
- <ul>
-<li><a href="/reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
- </ul>
-</li>
-
-<li class="nav-section">
-<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
-<ul>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
-<li><a href="/reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
-
-<li><a href="/reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
- </ul>
- </li>
-</ul>
-</li>
-
-
-
- <li class="nav-section">
- <div class="nav-section-header empty"><a href="/wear/license.html">License Agreement</a></div>
- </li>
-
-
-</ul>
-
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-
-
-
-
-<div class="col-12" id="doc-col" >
-
-
-
-
-
- <h1 itemprop="name" >Get Started with the Developer Preview</h1>
-
-
-
-
-
-
- <div id="jd-content">
-
-
- <div class="jd-descr" itemprop="articleBody">
- <div class="cols">
-
- <div class="col-5">
-<p>The Android Wear Developer Preview includes tools and APIs that allow you to
-enhance your app notifications
-to provide an optimized user experience on Android wearables.</p>
-
-<p>With the Android Wear Developer Preview, you can:</p>
-
-<ul>
- <li>Run the Android Wear platform in the Android emulator.</li>
- <li>Connect your Android device to the emulator and view notifications from the
-device as cards on Android Wear.</li>
- <li>Try new APIs in the preview support library that enhance your app's notifications
-with features such as voice replies and notification pages.</li>
-</ul>
-
-<p>To get access to the Developer Preview tools,
-click the sign up button on the right, then follow the setup instructions below.</p>
- </div>
-
- <div class="col-7">
-<img src="/wear/images/laptop-bridge.png" width="400" height="222" alt="" />
-
-<a href="/wear/preview/signup.html" class="button" style="
- width: 370px;
- margin: 10px 0 20px;
- font-weight: bold;
- font-size: 16px;
-">Sign Up for the Developer Preview</a>
-
-<p>Signing up provides you access to:</p>
-<ul>
-<li>New notification APIs in the preview support library.</li>
-<li>Sample apps using the new notification APIs.</li>
-<li>The <em>Android Wear Preview</em> app for your mobile device, which connects
-your device to the Android Wear emulator.</li>
-</ul>
-
- </div>
-</div>
-
-
-<p class="caution"><strong>Caution:</strong>
-The current Android Wear Developer Preview is intended for <b>development and testing purposes only</b>, not for production apps. Google may change this Developer Preview significantly prior to the official release of the Android Wear SDK. You may not publicly distribute or ship any application using this Developer Preview, as this Developer Preview will no longer be supported after the official SDK is released (which will cause applications based only on the Developer Preview to break).</p>
-
-
-
-
-<h2 id="Prereq">Prerequisites</h2>
-
-<p>Before you begin the setup, you must:</p>
-
-<ol>
- <li><a href="/sdk/index.html"><b>Install the Android SDK</b></a>.
- <p>The Android SDK includes all the developer tools required to build
-apps for Android (optional IDEs are also available for download).</p></li>
- <li><a href="/wear/preview/signup.html"><b>Sign up for the Android Wear Developer Preview</b></a>.
- <p>You must sign up with a Gmail or other Google account in order to download the
-preview support library and receive access to the
-<em>Android Wear Preview</em> beta app on Google Play Store.</p></li>
-</ol>
-
-<p class="note"><strong>Note:</strong>
-If you're using the ADT plugin for Eclipse, you must update to version 22.6.1 or higher.
-If you're using Android Studio, you must update to version 0.5.1 or higher</p>
-
-
-
-<h2 id="Install">1. Install the Android Wear System Image</h2>
-
-
-<ol>
- <li>Launch <a href="/tools/help/sdk-manager.html"
- >Android SDK Manager</a>.
- <ul>
- <li>From Eclipse, select <b>Window > Android SDK Manager</b>.</li>
- <li>From Android Studio, select <b>Tools > Android > SDK Manager</b>.</li>
- </ul>
- </li>
- <li>Below Tools, verify that you have Android SDK Tools revision 22.6 or higher.
- <p>If your version of Android SDK Tools is lower than 22.6, you must update:</p>
- <ol>
- <li>Select <strong>Android SDK Tools</strong>.</li>
- <li>Click <strong>Install package</strong>.</li>
- <li>Accept the license and click <strong>Install</strong>.</li>
- <li>When the installation completes, restart Android SDK Manager.</li>
- </ol>
- </li>
-
- <li>Below Android 4.4.2, select <strong>Android Wear ARM EABI v7a System Image</strong>.
-<p class="note"><strong>Note:</strong> Android Wear is designed to support multiple processor architectures.
-</p></li>
- <li>Below Extras, ensure that you have the latest version of the
-<a href="/tools/support-library/index.html">Android Support Library</a>.
- If an update is available, select <strong>Android Support Library</strong>. If you're using Android Studio, also select <strong>Android Support Repository</strong>.</li>
- <li>Click <strong>Install packages</strong>.</li>
- <li>Accept the license and click <strong>Install</strong>.</li>
-</ol>
-
-
-
-<h2 id="SetupEmulator">2. Set Up the Android Wear Emulator</h2>
-
-<ol>
-<li>Launch the <a href="/tools/help/avd-manager.html"
- >Android Virtual Device Manager</a>.
-<ul>
-<li>From Eclipse, select <b>Window > Android Virtual Device Manager</b>.</li>
-<li>From Android Studio, select <b>Tools > Android > AVD Manager</b>.</li>
-</ul>
-</li>
-<li>Click <strong>New</strong>.</li>
-<li>For the AVD Name, enter "AndroidWearSquare" or "AndroidWearRound", depending on whether
-you want to create an emulator with a square or round display.</li>
-<li>For the Device, select <strong>Android Wear Square</strong> or
- <strong>Android Wear Round</strong>.</li>
-<li>For the Target, select <strong>Android 4.4.2 - API Level 19</strong> (or higher).</li>
-<li>For the CPU/ABI, select <strong>Android Wear ARM (armeabi-v7a)</strong>.
-<p class="note"><strong>Note:</strong> Android Wear is designed to support multiple processor architectures.
-</p></li>
-<li>For the Skin, select <strong>AndroidWearSquare</strong> or
-<strong>AndroidWearRound</strong>.</li>
-<li>Leave all other options set to their defaults and click <strong>OK</strong>.
- <p>Although real Android wearables do not provide a keyboard as an input method,
- you should keep <strong>Hardware keyboard present</strong> selected so you can
- provide text input on screens where users will instead provide voice input.</p>
-</li>
-<!--
-<li>Click <strong>Device Definitions</strong>.</li>
-<li>Select <strong>Android WearSquare</strong> then click <strong>Create AVD</strong>.</li>
-<li>Click <strong>OK</strong>.</li>
--->
-<li>In the list of AVDs, select the one you just created and click
- <strong>Start</strong>. In the following window, click <strong>Launch</strong>.</li>
-</ol>
-
-<p>The Android Wear emulator now starts. To begin testing your app's notifications,
-you must now pair the emulator to your development device
-that has the <em>Android Wear Preview</em> app installed.</p>
-
-<p class="note"><strong>Tip:</strong> To improve the emulator startup time, edit your AVD
-and enable <strong>Snapshot</strong> under Emulator Options. When you start the emulator,
-select <strong>Save to snapshot</strong> then click <strong>Launch</strong>. Once the emulator
-is running, close it to save a snapshot of the system.
-Start the AVD again, but select <strong>Launch from snapshot</strong> and
-deselect <strong>Save to snapshot</strong>.</p>
-
-<p class="caution"><strong>Caution:</strong> Do not install apps on the Android Wear emulator.
-The system does not support traditional Android apps and the result of running such apps is
-unpredictable.</p>
-
-
-
-<h2 id="SetupApp">3. Set Up the Android Wear Preview App</h2>
-
-<p>To view your app's notifications on the Android Wear emulator, you must have the
-<em>Android Wear Preview</em> app installed on your Android device (a phone or tablet).</p>
-
-<p>To receive the Android Wear Preview app, you must <a
-href="/wear/preview/signup.html">sign up for the Developer Preview</a> using the same
-Gmail or Google account you use with Google Play Store.</p>
-</p>
-
-<p class="note"><strong>Note:</strong> The <em>Android Wear Preview</em> app is compatible with
- Android 4.3 and higher and is not available for the Android emulator.</p>
-
-<p>After you've signed up for the Developer Preview,
- you'll receive a confirmation email that includes a link to opt-in to the
- <em>Android Wear Preview</em> app beta program. Once you opt-in, it may take up to 24 hours for the
- app to become available in Google Play Store.</p>
-
-<p>After you install the <em>Android Wear Preview</em> app, you can set up
- your device to communicate with the Android Wear emulator:</p>
-
-<ol>
-<li>Open the <em>Android Wear Preview</em> app. You should see a notice that the app is currently
- not enabled as a notification listener. Tap the message to open the system settings,
- then select Android Wear Preview to grant it notification access.</li>
-<li>Connect your device to your development machine over USB. Be sure that no other
- Android devices are connected to the machine.</li>
-<li>Ensure that the Android Wear emulator (created in the previous section) is running.
-The emulator should show the time and an icon that indicates no device is connected.</li>
-<li>Open a command line terminal, navigate to your Android SDK's <code>platform-tools/</code>
-directory, then execute:
-<pre style="margin-top:.5em">adb -d forward tcp:5601 tcp:5601</pre></li>
-<li>Return to the Android Wear Preview app. It should now indicate that it is connected to
- the emulator. The Android Wear emulator should now show the 'g' orb icon, indicating
- that is is connected to your device.
-</ol>
-
-<p>Now, notifications from your device also appear in the Android Wear emulator.</p>
-
-
-
-
-<h2 id="AddLibrary">4. Add the Support Library to Your Project</h2>
-
-<p>The Android Wear preview support library includes several APIs that allow you to
-optimize your app's notifications for the Android Wear user experience.</p>
-
-<p>To receive the preview support library, you must <a
-href="/wear/preview/signup.html">sign up for the Developer Preview</a>. The
-confirmation email you receive after you sign up includes a link to download a ZIP file,
-which contains the preview support library and some sample apps.</p>
-
-<p>After you download and unzip the package, add the preview support library
-sto your Android project:</p>
-
-<p><b>If you're using Eclipse:</b></p>
- <ol>
- <li>In your Android app project, create a <code>libs/</code> directory in your project root
- (the same location as the <code>AndroidManifest.xml</code> file).</li>
- <li>Copy the v4 support library JAR file from your Android SDK directory (e.g.,
- <code><sdk>/extras/android/support/v4/android-support-v4.jar</code>) into your
- project <code>libs/</code> directory.
- <li>Also save the <code>wearable-preview-support.jar</code> file in the <code>libs/</code> directory.
- <li>Right click each JAR file and select <strong>Build Path > Add to Build Path</strong>.</li>
- </ol>
-
- <p><b>If you're using Android Studio:</b></p>
- <ol>
- <li>In your Android app project, create a <code>libs/</code> directory in your project root
- (the same location as the <code>AndroidManifest.xml</code> file).</li>
- <li>Save the <code>wearable-preview-support.jar</code> file in the <code>libs/</code> directory.
- <li>Open the <code>build.gradle</code> file in your app module.</li>
- <li>Add a dependency rule for both the v4 support library and the Android Wear
- preview support library:
-<pre>
-dependencies {
- compile "com.android.support:support-v4:18.0.+"
- compile files('../libs/wearable-preview-support.jar')
-}
-</pre>
- </li>
- <li>Click <strong>Sync Project with Gradle Files</strong> in the toolbar.</li>
- </ol>
-
-<p>To start optimizing your notifications for Android Wear,
- read <a href="/wear/notifications/creating.html"
- >Creating Notifications for Android Wear</a>.</p>
-
-
-
-</body>
-</html>
-
- </div>
-
- <div class="content-footer layout-content-row"
- itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div class="layout-content-col col-9" style="padding-top:4px">
-
- <div class="g-plusone" data-size="medium"></div>
-
- </div>
-
- <div class="paging-links layout-content-col col-4">
-
- </div>
-
- </div>
-
-
-
-
- </div> <!-- end jd-content -->
-
-<div id="footer" class="wrap" >
-
-
- <div id="copyright">
-
- Except as noted, this content is
- licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
- Creative Commons Attribution 2.5</a>. For details and
- restrictions, see the <a href="/license.html">Content
- License</a>.
- </div>
-
-
- <div id="footerlinks">
-
- <p>
- <a href="/about/index.html">About Android</a> |
- <a href="/legal.html">Legal</a> |
- <a href="/support.html">Support</a>
- </p>
- </div>
-
-</div> <!-- end footer -->
-</div><!-- end doc-content -->
-
-</div> <!-- end body-content -->
-
-
-
-
-
-
-<!-- Start of Tag -->
-<script type="text/javascript">
-var axel = Math.random() + "";
-var a = axel * 10000000000000;
-document.write('<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=' + a + '?" width="1" height="1" frameborder="0" style="display:none"></iframe>');
-</script>
-<noscript>
-<iframe src="https://2507573.fls.doubleclick.net/activityi;src=2507573;type=other026;cat=googl348;ord=1?" width="1" height="1" frameborder="0" style="display:none"></iframe>
-</noscript>
-<!-- End of Tag -->
-</body>
-</html>
-
-
-
diff --git a/docs/html/wear/preview/start.jd b/docs/html/wear/preview/start.jd
new file mode 100644
index 0000000..f8f0129
--- /dev/null
+++ b/docs/html/wear/preview/start.jd
@@ -0,0 +1,254 @@
+page.title=Get Started with the Developer Preview
+
+@jd:body
+
+
+<div class="cols">
+
+ <div class="col-5">
+<p>The Android Wear Developer Preview includes tools and APIs that allow you to
+enhance your app notifications
+to provide an optimized user experience on Android wearables.</p>
+
+<p>With the Android Wear Developer Preview, you can:</p>
+
+<ul>
+ <li>Run the Android Wear platform in the Android emulator.</li>
+ <li>Connect your Android device to the emulator and view notifications from the
+device as cards on Android Wear.</li>
+ <li>Try new APIs in the preview support library that enhance your app's notifications
+with features such as voice replies and notification pages.</li>
+</ul>
+
+<p>To get access to the Developer Preview tools,
+click the sign up button on the right, then follow the setup instructions below.</p>
+ </div>
+
+ <div class="col-7">
+<img src="/wear/images/laptop-bridge.png" width="400" height="222" alt="" />
+
+<a href="/wear/preview/signup.html" class="button" style="
+ width: 370px;
+ margin: 10px 0 20px;
+ font-weight: bold;
+ font-size: 16px;
+">Sign Up for the Developer Preview</a>
+
+<p>Signing up provides you access to:</p>
+<ul>
+<li>New notification APIs in the preview support library.</li>
+<li>Sample apps using the new notification APIs.</li>
+<li>The <em>Android Wear Preview</em> app for your mobile device, which connects
+your device to the Android Wear emulator.</li>
+</ul>
+
+ </div>
+</div>
+
+
+<p class="caution"><strong>Caution:</strong>
+The current Android Wear Developer Preview is intended for <b>development and testing purposes only</b>, not for production apps. Google may change this Developer Preview significantly prior to the official release of the Android Wear SDK. You may not publicly distribute or ship any application using this Developer Preview, as this Developer Preview will no longer be supported after the official SDK is released (which will cause applications based only on the Developer Preview to break).</p>
+
+
+
+
+<h2 id="Prereq">Prerequisites</h2>
+
+<p>Before you begin the setup, you must:</p>
+
+<ol>
+ <li><a href="{@docRoot}sdk/index.html"><b>Install the Android SDK</b></a>.
+ <p>The Android SDK includes all the developer tools required to build
+apps for Android (optional IDEs are also available for download).</p></li>
+ <li><a href="{@docRoot}wear/preview/signup.html"><b>Sign up for the Android Wear Developer Preview</b></a>.
+ <p>You must sign up with a Gmail or other Google account in order to download the
+preview support library and receive access to the
+<em>Android Wear Preview</em> beta app on Google Play Store.</p></li>
+</ol>
+
+<p class="note"><strong>Note:</strong>
+If you're using the ADT plugin for Eclipse, you must update to version 22.6.1 or higher.
+If you're using Android Studio, you must update to version 0.5.1 or higher</p>
+
+
+
+<h2 id="Install">1. Install the Android Wear System Image</h2>
+
+
+<ol>
+ <li>Launch <a href="{@docRoot}tools/help/sdk-manager.html"
+ >Android SDK Manager</a>.
+ <ul>
+ <li>From Eclipse, select <b>Window > Android SDK Manager</b>.</li>
+ <li>From Android Studio, select <b>Tools > Android > SDK Manager</b>.</li>
+ </ul>
+ </li>
+ <li>Below Tools, verify that you have Android SDK Tools revision 22.6 or higher.
+ <p>If your version of Android SDK Tools is lower than 22.6, you must update:</p>
+ <ol>
+ <li>Select <strong>Android SDK Tools</strong>.</li>
+ <li>Click <strong>Install package</strong>.</li>
+ <li>Accept the license and click <strong>Install</strong>.</li>
+ <li>When the installation completes, restart Android SDK Manager.</li>
+ </ol>
+ </li>
+
+ <li>Below Android 4.4.2, select <strong>Android Wear ARM EABI v7a System Image</strong>.
+<p class="note"><strong>Note:</strong> Android Wear is designed to support multiple processor architectures.
+</p></li>
+ <li>Below Extras, ensure that you have the latest version of the
+<a href="{@docRoot}tools/support-library/index.html">Android Support Library</a>.
+ If an update is available, select <strong>Android Support Library</strong>. If you're using Android Studio, also select <strong>Android Support Repository</strong>.</li>
+ <li>Click <strong>Install packages</strong>.</li>
+ <li>Accept the license and click <strong>Install</strong>.</li>
+</ol>
+
+
+
+<h2 id="SetupEmulator">2. Set Up the Android Wear Emulator</h2>
+
+<ol>
+<li>Launch the <a href="{@docRoot}tools/help/avd-manager.html"
+ >Android Virtual Device Manager</a>.
+<ul>
+<li>From Eclipse, select <b>Window > Android Virtual Device Manager</b>.</li>
+<li>From Android Studio, select <b>Tools > Android > AVD Manager</b>.</li>
+</ul>
+</li>
+<li>Click <strong>New</strong>.</li>
+<li>For the AVD Name, enter "AndroidWearSquare" or "AndroidWearRound", depending on whether
+you want to create an emulator with a square or round display.</li>
+<li>For the Device, select <strong>Android Wear Square</strong> or
+ <strong>Android Wear Round</strong>.</li>
+<li>For the Target, select <strong>Android 4.4.2 - API Level 19</strong> (or higher).</li>
+<li>For the CPU/ABI, select <strong>Android Wear ARM (armeabi-v7a)</strong>.
+<p class="note"><strong>Note:</strong> Android Wear is designed to support multiple processor architectures.
+</p></li>
+<li>For the Skin, select <strong>AndroidWearSquare</strong> or
+<strong>AndroidWearRound</strong>.</li>
+<li>Leave all other options set to their defaults and click <strong>OK</strong>.
+ <p>Although real Android wearables do not provide a keyboard as an input method,
+ you should keep <strong>Hardware keyboard present</strong> selected so you can
+ provide text input on screens where users will instead provide voice input.</p>
+</li>
+<!--
+<li>Click <strong>Device Definitions</strong>.</li>
+<li>Select <strong>Android WearSquare</strong> then click <strong>Create AVD</strong>.</li>
+<li>Click <strong>OK</strong>.</li>
+-->
+<li>In the list of AVDs, select the one you just created and click
+ <strong>Start</strong>. In the following window, click <strong>Launch</strong>.</li>
+</ol>
+
+<p>The Android Wear emulator now starts. To begin testing your app's notifications,
+you must now pair the emulator to your development device
+that has the <em>Android Wear Preview</em> app installed.</p>
+
+<p class="note"><strong>Tip:</strong> To improve the emulator startup time, edit your AVD
+and enable <strong>Snapshot</strong> under Emulator Options. When you start the emulator,
+select <strong>Save to snapshot</strong> then click <strong>Launch</strong>. Once the emulator
+is running, close it to save a snapshot of the system.
+Start the AVD again, but select <strong>Launch from snapshot</strong> and
+deselect <strong>Save to snapshot</strong>.</p>
+
+<p class="caution"><strong>Caution:</strong> Do not install apps on the Android Wear emulator.
+The system does not support traditional Android apps and the result of running such apps is
+unpredictable.</p>
+
+
+
+<h2 id="SetupApp">3. Set Up the Android Wear Preview App</h2>
+
+<p>To view your app's notifications on the Android Wear emulator, you must have the
+<em>Android Wear Preview</em> app installed on your Android device (a phone or tablet).</p>
+
+<p>To receive the Android Wear Preview app, you must <a
+href="{@docRoot}wear/preview/signup.html">sign up for the Developer Preview</a> using the same
+Gmail or Google account you use with Google Play Store.</p>
+</p>
+
+<p class="note"><strong>Note:</strong> The <em>Android Wear Preview</em> app is compatible with
+ Android 4.3 and higher and is not available for the Android emulator.</p>
+
+<p>After you've signed up for the Developer Preview,
+ you'll receive a confirmation email that includes a link to opt-in to the
+ <em>Android Wear Preview</em> app beta program. Once you opt-in, it may take up to 24 hours for the
+ app to become available in Google Play Store.</p>
+
+<p>After you install the <em>Android Wear Preview</em> app, you can set up
+ your device to communicate with the Android Wear emulator:</p>
+
+<ol>
+<li>Open the <em>Android Wear Preview</em> app. You should see a notice that the app is currently
+ not enabled as a notification listener. Tap the message to open the system settings,
+ then select Android Wear Preview to grant it notification access.</li>
+<li>Connect your device to your development machine over USB. Be sure that no other
+ Android devices are connected to the machine.</li>
+<li>Ensure that the Android Wear emulator (created in the previous section) is running.
+The emulator should show the time and an icon that indicates no device is connected.</li>
+<li>Open a command line terminal, navigate to your Android SDK's <code>platform-tools/</code>
+directory, then execute:
+<pre style="margin-top:.5em">adb -d forward tcp:5601 tcp:5601</pre>
+<p class="note"><strong>Note:</strong> You must execute this command each time you connect your
+device over USB.</p>
+</li>
+<li>Return to the Android Wear Preview app. It should now indicate that it is connected to
+ the emulator. The Android Wear emulator should now show the 'g' orb icon, indicating
+ that is is connected to your device.
+</ol>
+
+<p>Now, notifications from your device also appear in the Android Wear emulator.</p>
+
+
+
+
+<h2 id="AddLibrary">4. Add the Support Library to Your Project</h2>
+
+<p>The Android Wear preview support library includes several APIs that allow you to
+optimize your app's notifications for the Android Wear user experience.</p>
+
+<p>To receive the preview support library, you must <a
+href="{@docRoot}wear/preview/signup.html">sign up for the Developer Preview</a>. The
+confirmation email you receive after you sign up includes a link to download a ZIP file,
+which contains the preview support library and some sample apps.</p>
+
+<p>After you download and unzip the package, add the preview support library
+sto your Android project:</p>
+
+<p><b>If you're using Eclipse:</b></p>
+ <ol>
+ <li>In your Android app project, create a <code>libs/</code> directory in your project root
+ (the same location as the <code>AndroidManifest.xml</code> file).</li>
+ <li>Copy the v4 support library JAR file from your Android SDK directory (e.g.,
+ <code><sdk>/extras/android/support/v4/android-support-v4.jar</code>) into your
+ project <code>libs/</code> directory.
+ <li>Also save the <code>wearable-preview-support.jar</code> file in the <code>libs/</code> directory.
+ <li>Right click each JAR file and select <strong>Build Path > Add to Build Path</strong>.</li>
+ </ol>
+
+ <p><b>If you're using Android Studio:</b></p>
+ <ol>
+ <li>In your Android app project, create a <code>libs/</code> directory in your project root
+ (the same location as the <code>AndroidManifest.xml</code> file).</li>
+ <li>Save the <code>wearable-preview-support.jar</code> file in the <code>libs/</code> directory.
+ <li>Open the <code>build.gradle</code> file in your app module.</li>
+ <li>Add a dependency rule for both the v4 support library and the Android Wear
+ preview support library:
+<pre>
+dependencies {
+ compile "com.android.support:support-v4:18.0.+"
+ compile files('../libs/wearable-preview-support.jar')
+}
+</pre>
+ </li>
+ <li>Click <strong>Sync Project with Gradle Files</strong> in the toolbar.</li>
+ </ol>
+
+<p>To start optimizing your notifications for Android Wear,
+ read <a href="{@docRoot}wear/notifications/creating.html"
+ >Creating Notifications for Android Wear</a>.</p>
+
+
+
+</body>
+</html>
diff --git a/docs/html/wear/wear_toc.cs b/docs/html/wear/wear_toc.cs
new file mode 100644
index 0000000..65ac2e9
--- /dev/null
+++ b/docs/html/wear/wear_toc.cs
@@ -0,0 +1,74 @@
+<ul id="nav">
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/preview/start.html">Get Started
+ </a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/design/user-interface.html">UI Overview
+ </a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/design/index.html">Design Principles
+ </a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/notifications/creating.html">Creating Notifications for Android Wear
+ </a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/notifications/remote-input.html">Receiving Voice Input from a Notification
+ </a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/notifications/pages.html">Adding Pages to a Notification
+ </a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/notifications/stacks.html">Stacking Notifications
+ </a></div>
+ </li>
+
+ <li class="nav-section">
+ <div class="nav-section-header"><a href="<?cs var:toroot ?>reference/android/preview/support/package-summary.html">Notification Reference</a></div>
+ <ul class="tree-list-children">
+<li class="nav-section">
+<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.v4.app">android.preview.support.v4.app</span></div>
+ <ul>
+<li><a href="<?cs var:toroot ?>reference/android/preview/support/v4/app/NotificationManagerCompat.html">NotificationManagerCompat</a></li>
+ </ul>
+</li>
+
+<li class="nav-section">
+<div class="nav-section-header-ref"><span class="tree-list-subtitle package" title="android.preview.support.wearable.notifications">android.preview.support.wearable.notifications</span></div>
+<ul>
+
+<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/RemoteInput.html">RemoteInput</a></li>
+<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/RemoteInput.Builder.html" >RemoteInput.Builder</a></li>
+
+<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/WearableNotifications.html">WearableNotifications</a></li>
+
+<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/WearableNotifications.Action.html">WearableNotifications.Action</a></li>
+
+<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/WearableNotifications.Action.Builder.html">WearableNotifications.Action.Builder</a></li>
+
+<li><a href="<?cs var:toroot ?>reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html">WearableNotifications.Builder</a></li>
+ </ul>
+ </li>
+</ul>
+</li>
+
+
+
+ <li class="nav-section">
+ <div class="nav-section-header empty"><a href="<?cs var:toroot ?>wear/license.html">License Agreement</a></div>
+ </li>
+
+
+</ul>
diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._data.plist b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._data.plist
new file mode 100644
index 0000000..d82ea05
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._data.plist
Binary files differ
diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._image1.png b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._image1.png
new file mode 100644
index 0000000..3435e35
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/._image1.png
Binary files differ
diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/data.plist b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/data.plist
new file mode 100644
index 0000000..07791df
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/data.plist
Binary files differ
diff --git a/docs/image_sources/mediarouter/media-route-provider-framework.graffle/image1.png b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/image1.png
new file mode 100644
index 0000000..d6e3e95
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-route-provider-framework.graffle/image1.png
Binary files differ
diff --git a/docs/image_sources/mediarouter/media-router-framework.graffle/data.plist b/docs/image_sources/mediarouter/media-router-framework.graffle/data.plist
new file mode 100644
index 0000000..ffd8212
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-router-framework.graffle/data.plist
Binary files differ
diff --git a/docs/image_sources/mediarouter/media-router-framework.graffle/image1.png b/docs/image_sources/mediarouter/media-router-framework.graffle/image1.png
new file mode 100644
index 0000000..d6e3e95
--- /dev/null
+++ b/docs/image_sources/mediarouter/media-router-framework.graffle/image1.png
Binary files differ
diff --git a/graphics/java/android/graphics/TemporaryBuffer.java b/graphics/java/android/graphics/TemporaryBuffer.java
index c5b8143..36a2275 100644
--- a/graphics/java/android/graphics/TemporaryBuffer.java
+++ b/graphics/java/android/graphics/TemporaryBuffer.java
@@ -31,7 +31,7 @@
}
if (buf == null || buf.length < len) {
- buf = new char[ArrayUtils.idealCharArraySize(len)];
+ buf = ArrayUtils.newUnpaddedCharArray(len);
}
return buf;
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index de2b68f..1760458 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -121,20 +121,6 @@
* document.</p></div>
*/
public abstract class Drawable {
- /**
- * Hotspot identifier mask for tracking touch points.
- *
- * @hide until hotspot APIs are finalized
- */
- public static final int HOTSPOT_TOUCH_MASK = 0xFF;
-
- /**
- * Hotspot identifier for tracking keyboard focus.
- *
- * @hide until hotspot APIs are finalized
- */
- public static final int HOTSPOT_FOCUS = 0x100;
-
private static final Rect ZERO_BOUNDS_RECT = new Rect();
private int[] mStateSet = StateSet.WILD_CARD;
@@ -1054,14 +1040,14 @@
drawable = new LayerDrawable();
} else if (name.equals("transition")) {
drawable = new TransitionDrawable();
- } else if (name.equals("reveal")) {
- drawable = new RevealDrawable();
} else if (name.equals("touch-feedback")) {
drawable = new TouchFeedbackDrawable();
} else if (name.equals("color")) {
drawable = new ColorDrawable();
} else if (name.equals("shape")) {
drawable = new GradientDrawable();
+ } else if (name.equals("vector")) {
+ drawable = new VectorDrawable();
} else if (name.equals("scale")) {
drawable = new ScaleDrawable();
} else if (name.equals("clip")) {
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 3d48cda..52352c4 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -80,8 +80,8 @@
}
/**
- * Create a new layer drawable with the specified list of layers and the specified
- * constant state.
+ * Create a new layer drawable with the specified list of layers and the
+ * specified constant state.
*
* @param layers The list of layers to add to this drawable.
* @param state The constant drawable state.
@@ -326,6 +326,7 @@
childDrawable.mInsetR = right;
childDrawable.mInsetB = bottom;
st.mNum++;
+ st.invalidateCache();
layer.setCallback(this);
}
@@ -419,6 +420,7 @@
}
childDrawable.mDrawable = drawable;
+ mLayerState.invalidateCache();
return true;
}
}
@@ -527,6 +529,25 @@
}
}
+ private void computeStackedPadding(Rect padding) {
+ padding.left = 0;
+ padding.top = 0;
+ padding.right = 0;
+ padding.bottom = 0;
+
+ // Take the max padding.
+ final ChildDrawable[] array = mLayerState.mChildren;
+ final int N = mLayerState.mNum;
+ for (int i = 0; i < N; i++) {
+ refreshChildPadding(i, array[i]);
+
+ padding.left = Math.max(padding.left, mPaddingL[i]);
+ padding.top = Math.max(padding.top, mPaddingT[i]);
+ padding.right = Math.max(padding.right, mPaddingR[i]);
+ padding.bottom = Math.max(padding.bottom, mPaddingB[i]);
+ }
+ }
+
/**
* @hide
*/
@@ -579,25 +600,6 @@
}
}
- private void computeStackedPadding(Rect padding) {
- padding.left = 0;
- padding.top = 0;
- padding.right = 0;
- padding.bottom = 0;
-
- // Take the max padding.
- final ChildDrawable[] array = mLayerState.mChildren;
- final int N = mLayerState.mNum;
- for (int i = 0; i < N; i++) {
- refreshChildPadding(i, array[i]);
-
- padding.left = Math.max(padding.left, mPaddingL[i]);
- padding.top = Math.max(padding.top, mPaddingT[i]);
- padding.right = Math.max(padding.right, mPaddingR[i]);
- padding.bottom = Math.max(padding.bottom, mPaddingB[i]);
- }
- }
-
@Override
public boolean setVisible(boolean visible, boolean restart) {
final boolean changed = super.setVisible(visible, restart);
@@ -632,7 +634,8 @@
public int getAlpha() {
final ChildDrawable[] array = mLayerState.mChildren;
if (mLayerState.mNum > 0) {
- // All layers should have the same alpha set on them - just return the first one
+ // All layers should have the same alpha set on them - just return
+ // the first one
return array[0].mDrawable.getAlpha();
} else {
return super.getAlpha();
@@ -649,12 +652,11 @@
}
/**
- * Sets the opacity of this drawable directly, instead of collecting the states from
- * the layers
+ * Sets the opacity of this drawable directly, instead of collecting the
+ * states from the layers
*
- * @param opacity The opacity to use, or {@link PixelFormat#UNKNOWN PixelFormat.UNKNOWN}
- * for the default behavior
- *
+ * @param opacity The opacity to use, or {@link PixelFormat#UNKNOWN
+ * PixelFormat.UNKNOWN} for the default behavior
* @see PixelFormat#UNKNOWN
* @see PixelFormat#TRANSLUCENT
* @see PixelFormat#TRANSPARENT
@@ -702,7 +704,7 @@
final int N = mLayerState.mNum;
for (int i = 0; i < N; i++) {
final ChildDrawable r = array[i];
- if (r.mDrawable.setState(state)) {
+ if (r.mDrawable.isStateful() && r.mDrawable.setState(state)) {
changed = true;
}
@@ -839,7 +841,7 @@
/**
* Ensures the child padding caches are large enough.
*/
- private void ensurePadding() {
+ void ensurePadding() {
final int N = mLayerState.mNum;
if (mPaddingL != null && mPaddingL.length >= N) {
return;
@@ -890,7 +892,7 @@
public int[] mThemeAttrs;
public int mInsetL, mInsetT, mInsetR, mInsetB;
public int mId;
-
+
ChildDrawable() {
// Default empty constructor.
}
@@ -920,14 +922,11 @@
int mChangingConfigurations;
int mChildrenChangingConfigurations;
- private boolean mHaveOpacity = false;
+ private boolean mHaveOpacity;
private int mOpacity;
- private boolean mHaveStateful = false;
- private boolean mStateful;
-
- private boolean mCheckedConstantState;
- private boolean mCanConstantState;
+ private boolean mHaveIsStateful;
+ private boolean mIsStateful;
private boolean mAutoMirrored;
@@ -951,9 +950,8 @@
mHaveOpacity = orig.mHaveOpacity;
mOpacity = orig.mOpacity;
- mHaveStateful = orig.mHaveStateful;
- mStateful = orig.mStateful;
- mCheckedConstantState = mCanConstantState = true;
+ mHaveIsStateful = orig.mHaveIsStateful;
+ mIsStateful = orig.mIsStateful;
mAutoMirrored = orig.mAutoMirrored;
mPaddingMode = orig.mPaddingMode;
mThemeAttrs = orig.mThemeAttrs;
@@ -993,49 +991,54 @@
return mOpacity;
}
+ final ChildDrawable[] array = mChildren;
final int N = mNum;
- int op = N > 0 ? mChildren[0].mDrawable.getOpacity() : PixelFormat.TRANSPARENT;
+ int op = N > 0 ? array[0].mDrawable.getOpacity() : PixelFormat.TRANSPARENT;
for (int i = 1; i < N; i++) {
- op = Drawable.resolveOpacity(op, mChildren[i].mDrawable.getOpacity());
+ op = Drawable.resolveOpacity(op, array[i].mDrawable.getOpacity());
}
+
mOpacity = op;
mHaveOpacity = true;
return op;
}
public final boolean isStateful() {
- if (mHaveStateful) {
- return mStateful;
+ if (mHaveIsStateful) {
+ return mIsStateful;
}
- boolean stateful = false;
+ final ChildDrawable[] array = mChildren;
final int N = mNum;
+ boolean isStateful = false;
for (int i = 0; i < N; i++) {
- if (mChildren[i].mDrawable.isStateful()) {
- stateful = true;
+ if (array[i].mDrawable.isStateful()) {
+ isStateful = true;
break;
}
}
- mStateful = stateful;
- mHaveStateful = true;
- return stateful;
+ mIsStateful = isStateful;
+ mHaveIsStateful = true;
+ return isStateful;
}
- public boolean canConstantState() {
- if (!mCheckedConstantState && mChildren != null) {
- mCanConstantState = true;
- final int N = mNum;
- for (int i = 0; i < N; i++) {
- if (mChildren[i].mDrawable.getConstantState() == null) {
- mCanConstantState = false;
- break;
- }
+ public final boolean canConstantState() {
+ final ChildDrawable[] array = mChildren;
+ final int N = mNum;
+ for (int i = 0; i < N; i++) {
+ if (array[i].mDrawable.getConstantState() == null) {
+ return false;
}
- mCheckedConstantState = true;
}
- return mCanConstantState;
+ // Don't cache the result, this method is not called very often.
+ return true;
+ }
+
+ public void invalidateCache() {
+ mHaveOpacity = false;
+ mHaveIsStateful = false;
}
}
}
diff --git a/graphics/java/android/graphics/drawable/RevealDrawable.java b/graphics/java/android/graphics/drawable/RevealDrawable.java
deleted file mode 100644
index 2f96fe4..0000000
--- a/graphics/java/android/graphics/drawable/RevealDrawable.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (C) 2013 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.graphics.drawable;
-
-import android.content.res.Resources;
-import android.content.res.Resources.Theme;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.PorterDuff.Mode;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.os.SystemClock;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.SparseArray;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-/**
- * An extension of LayerDrawable that is intended to react to touch hotspots
- * and reveal the second layer atop the first.
- * <p>
- * It can be defined in an XML file with the <code><reveal></code> element.
- * Each Drawable in the transition is defined in a nested <code><item></code>.
- * For more information, see the guide to <a href="{@docRoot}
- * guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
- *
- * @attr ref android.R.styleable#LayerDrawableItem_left
- * @attr ref android.R.styleable#LayerDrawableItem_top
- * @attr ref android.R.styleable#LayerDrawableItem_right
- * @attr ref android.R.styleable#LayerDrawableItem_bottom
- * @attr ref android.R.styleable#LayerDrawableItem_drawable
- * @attr ref android.R.styleable#LayerDrawableItem_id
- */
-public class RevealDrawable extends LayerDrawable {
- private final Rect mTempRect = new Rect();
-
- /** Lazily-created map of touch hotspot IDs to ripples. */
- private SparseArray<Ripple> mTouchedRipples;
-
- /** Lazily-created list of actively animating ripples. */
- private ArrayList<Ripple> mActiveRipples;
-
- /** Lazily-created runnable for scheduling invalidation. */
- private Runnable mAnimationRunnable;
-
- /** Whether the animation runnable has been posted. */
- private boolean mAnimating;
-
- /** Target density, used to scale density-independent pixels. */
- private float mDensity = 1.0f;
-
- /** Paint used to control appearance of ripples. */
- private Paint mRipplePaint;
-
- /** Paint used to control reveal layer masking. */
- private Paint mMaskingPaint;
-
- /**
- * Create a new reveal drawable with the specified list of layers. At least
- * two layers are required for this drawable to work properly.
- */
- public RevealDrawable(Drawable[] layers) {
- this(new RevealState(null, null, null), layers);
- }
-
- /**
- * Create a new reveal drawable with no layers. To work correctly, at least
- * two layers must be added to this drawable.
- *
- * @see #RevealDrawable(Drawable[])
- */
- RevealDrawable() {
- this(new RevealState(null, null, null), (Resources) null, null);
- }
-
- private RevealDrawable(RevealState state, Resources res) {
- super(state, res, null);
- }
-
- private RevealDrawable(RevealState state, Resources res, Theme theme) {
- super(state, res, theme);
- }
-
- private RevealDrawable(RevealState state, Drawable[] layers) {
- super(layers, state);
- }
-
- @Override
- public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
- throws XmlPullParserException, IOException {
- super.inflate(r, parser, attrs, theme);
-
- setTargetDensity(r.getDisplayMetrics());
- setPaddingMode(PADDING_MODE_STACK);
- }
-
- @Override
- LayerState createConstantState(LayerState state, Resources res) {
- return new RevealState((RevealState) state, this, res);
- }
-
- /**
- * Set the density at which this drawable will be rendered.
- *
- * @param metrics The display metrics for this drawable.
- */
- private void setTargetDensity(DisplayMetrics metrics) {
- if (mDensity != metrics.density) {
- mDensity = metrics.density;
- invalidateSelf();
- }
- }
-
- /**
- * @hide until hotspot APIs are finalized
- */
- @Override
- public boolean supportsHotspots() {
- return true;
- }
-
- /**
- * @hide until hotspot APIs are finalized
- */
- @Override
- public void setHotspot(int id, float x, float y) {
- if (mTouchedRipples == null) {
- mTouchedRipples = new SparseArray<Ripple>();
- mActiveRipples = new ArrayList<Ripple>();
- }
-
- final Ripple ripple = mTouchedRipples.get(id);
- if (ripple == null) {
- final Rect padding = mTempRect;
- getPadding(padding);
-
- final Ripple newRipple = new Ripple(getBounds(), padding, x, y, mDensity);
- newRipple.enter();
-
- mActiveRipples.add(newRipple);
- mTouchedRipples.put(id, newRipple);
- } else {
- ripple.move(x, y);
- }
-
- scheduleAnimation();
- }
-
- /**
- * @hide until hotspot APIs are finalized
- */
- @Override
- public void removeHotspot(int id) {
- if (mTouchedRipples == null) {
- return;
- }
-
- final Ripple ripple = mTouchedRipples.get(id);
- if (ripple != null) {
- ripple.exit();
-
- mTouchedRipples.remove(id);
- scheduleAnimation();
- }
- }
-
- /**
- * @hide until hotspot APIs are finalized
- */
- @Override
- public void clearHotspots() {
- if (mTouchedRipples == null) {
- return;
- }
-
- final int n = mTouchedRipples.size();
- for (int i = 0; i < n; i++) {
- final Ripple ripple = mTouchedRipples.valueAt(i);
- ripple.exit();
- }
-
- if (n > 0) {
- mTouchedRipples.clear();
- scheduleAnimation();
- }
- }
-
- /**
- * Schedules the next animation, if necessary.
- */
- private void scheduleAnimation() {
- if (mActiveRipples == null || mActiveRipples.isEmpty()) {
- mAnimating = false;
- } else if (!mAnimating) {
- mAnimating = true;
-
- if (mAnimationRunnable == null) {
- mAnimationRunnable = new Runnable() {
- @Override
- public void run() {
- mAnimating = false;
- scheduleAnimation();
- invalidateSelf();
- }
- };
- }
-
- scheduleSelf(mAnimationRunnable, SystemClock.uptimeMillis() + 1000 / 60);
- }
- }
-
- @Override
- public void draw(Canvas canvas) {
- final int layerCount = getNumberOfLayers();
- if (layerCount == 0) {
- return;
- }
-
- getDrawable(0).draw(canvas);
-
- final Rect bounds = getBounds();
- final ArrayList<Ripple> activeRipples = mActiveRipples;
- if (layerCount == 1 || bounds.isEmpty() || activeRipples == null
- || activeRipples.isEmpty()) {
- // Nothing to reveal, we're done here.
- return;
- }
-
- if (mRipplePaint == null) {
- mRipplePaint = new Paint();
- mRipplePaint.setAntiAlias(true);
- }
-
- // Draw ripple mask into a buffer that merges using SRC_OVER.
- boolean needsMask = false;
- int layerSaveCount = -1;
- int n = activeRipples.size();
- for (int i = 0; i < n; i++) {
- final Ripple ripple = activeRipples.get(i);
- if (!ripple.active()) {
- activeRipples.remove(i);
- i--;
- n--;
- } else {
- if (layerSaveCount < 0) {
- layerSaveCount = canvas.saveLayer(
- bounds.left, bounds.top, bounds.right, bounds.bottom, null, 0);
- // Ripples must be clipped to bounds, otherwise SRC_IN will
- // miss them and we'll get artifacts.
- canvas.clipRect(bounds);
- }
-
- needsMask |= ripple.draw(canvas, mRipplePaint);
- }
- }
-
- // If a layer was saved, it contains the ripple mask. Draw the reveal
- // into another layer and composite using SRC_IN, then composite onto
- // the original canvas.
- if (layerSaveCount >= 0) {
- if (needsMask) {
- if (mMaskingPaint == null) {
- mMaskingPaint = new Paint();
- mMaskingPaint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
- }
-
- // TODO: When Drawable.setXfermode() is supported by all drawables,
- // we won't need an extra layer.
- canvas.saveLayer(
- bounds.left, bounds.top, bounds.right, bounds.bottom, mMaskingPaint, 0);
- getDrawable(1).draw(canvas);
- }
-
- canvas.restoreToCount(layerSaveCount);
- }
- }
-
- private static class RevealState extends LayerState {
- public RevealState(RevealState orig, RevealDrawable owner, Resources res) {
- super(orig, owner, res);
- }
-
- @Override
- public Drawable newDrawable() {
- return newDrawable(null);
- }
-
- @Override
- public Drawable newDrawable(Resources res) {
- return new RevealDrawable(this, res);
- }
-
- @Override
- public Drawable newDrawable(Resources res, Theme theme) {
- return new RevealDrawable(this, res, theme);
- }
- }
-}
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index 618afb8..03dd841 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -43,34 +43,16 @@
/** Resistance factor when constraining outside touches. */
private static final float OUTSIDE_RESISTANCE = 0.7f;
- /** Duration for animating the trailing edge of the ripple. */
- private static final int EXIT_DURATION = 600;
-
- /** Duration for animating the leading edge of the ripple. */
- private static final int ENTER_DURATION = 400;
-
- /** Minimum elapsed time between start of enter and exit animations. */
- private static final int EXIT_MIN_DELAY = 200;
-
- /** Duration for animating between inside and outside touch. */
- private static final int OUTSIDE_DURATION = 300;
-
- /** Duration for animating pulses. */
- private static final int PULSE_DURATION = 400;
-
- /** Interval between pulses while inside and fully entered. */
- private static final int PULSE_INTERVAL = 400;
-
/** Minimum alpha value during a pulse animation. */
private static final int PULSE_MIN_ALPHA = 128;
- /** Delay before pulses start. */
- private static final int PULSE_DELAY = 500;
-
private final Rect mBounds;
private final Rect mPadding;
- private final int mMinRadius;
- private final int mOutsideRadius;
+
+ private RippleAnimator mAnimator;
+
+ private int mMinRadius;
+ private int mOutsideRadius;
/** Center x-coordinate. */
private float mX;
@@ -80,15 +62,18 @@
/** Whether the center is within the parent bounds. */
private boolean mInside;
+
+ /** Enter state. A value in [0...1] or -1 if not set. */
+ private float mEnterState = -1;
- /** When the ripple started appearing. */
- private long mEnterTime = -1;
+ /** Exit state. A value in [0...1] or -1 if not set. */
+ private float mExitState = -1;
- /** When the ripple started vanishing. */
- private long mExitTime = -1;
+ /** Outside state. A value in [0...1] or -1 if not set. */
+ private float mOutsideState = -1;
- /** When the ripple last transitioned between inside and outside touch. */
- private long mOutsideTime = -1;
+ /** Pulse state. A value in [0...1] or -1 if not set. */
+ private float mPulseState = -1;
/**
* Creates a new ripple with the specified parent bounds, padding, initial
@@ -105,6 +90,14 @@
mMinRadius = (int) (density * STARTING_RADIUS_DP + 0.5f);
mOutsideRadius = (int) (density * OUTSIDE_RADIUS_DP + 0.5f);
}
+
+ public void setMinRadius(int minRadius) {
+ mMinRadius = minRadius;
+ }
+
+ public void setOutsideRadius(int outsideRadius) {
+ mOutsideRadius = outsideRadius;
+ }
/**
* Updates the center coordinates.
@@ -115,49 +108,18 @@
final boolean inside = mBounds.contains((int) x, (int) y);
if (mInside != inside) {
- mOutsideTime = AnimationUtils.currentAnimationTimeMillis();
+ if (mAnimator != null) {
+ mAnimator.outside();
+ }
mInside = inside;
}
}
- /**
- * Starts the enter animation.
- */
- public void enter() {
- mEnterTime = AnimationUtils.currentAnimationTimeMillis();
- }
-
- /**
- * Starts the exit animation. If {@link #enter()} was called recently, the
- * animation may be postponed.
- */
- public void exit() {
- final long minTime = mEnterTime + EXIT_MIN_DELAY;
- mExitTime = Math.max(minTime, AnimationUtils.currentAnimationTimeMillis());
- }
-
- /**
- * Returns whether this ripple is currently animating.
- */
- public boolean active() {
- final long currentTime = AnimationUtils.currentAnimationTimeMillis();
- return mEnterTime >= 0 && mEnterTime <= currentTime
- && (mExitTime < 0 || currentTime <= mExitTime + EXIT_DURATION);
- }
-
- /**
- * Constrains a value within a specified asymptotic margin outside a minimum
- * and maximum.
- */
- private static float looseConstrain(float value, float min, float max, float margin,
- float factor) {
- if (value < min) {
- return min - Math.min(margin, (float) Math.pow(min - value, factor));
- } else if (value > max) {
- return max + Math.min(margin, (float) Math.pow(value - max, factor));
- } else {
- return value;
+ public RippleAnimator animate() {
+ if (mAnimator == null) {
+ mAnimator = new RippleAnimator(this);
}
+ return mAnimator;
}
public boolean draw(Canvas c, Paint p) {
@@ -167,17 +129,10 @@
final float dY = Math.max(mY, bounds.bottom - mY);
final int maxRadius = (int) Math.ceil(Math.sqrt(dX * dX + dY * dY));
- // Track three states:
- // - Enter: touch begins, affects outer radius
- // - Outside: touch moves outside bounds, affects maximum outer radius
- // - Exit: touch ends, affects inner radius
- final long currentTime = AnimationUtils.currentAnimationTimeMillis();
- final float enterState = mEnterTime < 0 ? 0 : INTERPOLATOR.getInterpolation(
- MathUtils.constrain((currentTime - mEnterTime) / (float) ENTER_DURATION, 0, 1));
- final float outsideState = mOutsideTime < 0 ? 1 : INTERPOLATOR.getInterpolation(
- MathUtils.constrain((currentTime - mOutsideTime) / (float) OUTSIDE_DURATION, 0, 1));
- final float exitState = mExitTime < 0 ? 0 : INTERPOLATOR.getInterpolation(
- MathUtils.constrain((currentTime - mExitTime) / (float) EXIT_DURATION, 0, 1));
+ final float enterState = mEnterState;
+ final float exitState = mExitState;
+ final float outsideState = mOutsideState;
+ final float pulseState = mPulseState;
final float insideRadius = MathUtils.lerp(mMinRadius, maxRadius, enterState);
final float outerRadius = MathUtils.lerp(mOutsideRadius, insideRadius,
mInside ? outsideState : 1 - outsideState);
@@ -189,35 +144,28 @@
outerRadius * OUTSIDE_MARGIN, OUTSIDE_RESISTANCE);
// Compute maximum alpha, taking pulse into account when active.
- final long pulseTime = (currentTime - mEnterTime - ENTER_DURATION - PULSE_DELAY);
final int maxAlpha;
- if (pulseTime < 0) {
+ if (pulseState < 0 || pulseState >= 1) {
maxAlpha = 255;
} else {
- final float pulseState = (pulseTime % (PULSE_INTERVAL + PULSE_DURATION))
- / (float) PULSE_DURATION;
- if (pulseState >= 1) {
- maxAlpha = 255;
+ final float pulseAlpha;
+ if (pulseState > 0.5) {
+ // Pulsing in to max alpha.
+ pulseAlpha = MathUtils.lerp(PULSE_MIN_ALPHA, 255, (pulseState - .5f) * 2);
} else {
- final float pulseAlpha;
- if (pulseState > 0.5) {
- // Pulsing in to max alpha.
- pulseAlpha = MathUtils.lerp(PULSE_MIN_ALPHA, 255, (pulseState - .5f) * 2);
- } else {
- // Pulsing out to min alpha.
- pulseAlpha = MathUtils.lerp(255, PULSE_MIN_ALPHA, pulseState * 2f);
- }
+ // Pulsing out to min alpha.
+ pulseAlpha = MathUtils.lerp(255, PULSE_MIN_ALPHA, pulseState * 2f);
+ }
- if (exitState > 0) {
- // Animating exit, interpolate pulse with exit state.
- maxAlpha = (int) (MathUtils.lerp(255, pulseAlpha, exitState) + 0.5f);
- } else if (mInside) {
- // No animation, no need to interpolate.
- maxAlpha = (int) (pulseAlpha + 0.5f);
- } else {
- // Animating inside, interpolate pulse with inside state.
- maxAlpha = (int) (MathUtils.lerp(pulseAlpha, 255, outsideState) + 0.5f);
- }
+ if (exitState > 0) {
+ // Animating exit, interpolate pulse with exit state.
+ maxAlpha = (int) (MathUtils.lerp(255, pulseAlpha, exitState) + 0.5f);
+ } else if (mInside) {
+ // No animation, no need to interpolate.
+ maxAlpha = (int) (pulseAlpha + 0.5f);
+ } else {
+ // Animating inside, interpolate pulse with inside state.
+ maxAlpha = (int) (MathUtils.lerp(pulseAlpha, 255, outsideState) + 0.5f);
}
}
@@ -260,4 +208,109 @@
final int maxRadius = (int) Math.ceil(Math.sqrt(dX * dX + dY * dY));
bounds.set(x - maxRadius, y - maxRadius, x + maxRadius, y + maxRadius);
}
+
+ /**
+ * Constrains a value within a specified asymptotic margin outside a minimum
+ * and maximum.
+ */
+ private static float looseConstrain(float value, float min, float max, float margin,
+ float factor) {
+ if (value < min) {
+ return min - Math.min(margin, (float) Math.pow(min - value, factor));
+ } else if (value > max) {
+ return max + Math.min(margin, (float) Math.pow(value - max, factor));
+ } else {
+ return value;
+ }
+ }
+
+ public static class RippleAnimator {
+ /** Duration for animating the trailing edge of the ripple. */
+ private static final int EXIT_DURATION = 600;
+
+ /** Duration for animating the leading edge of the ripple. */
+ private static final int ENTER_DURATION = 400;
+
+ /** Minimum elapsed time between start of enter and exit animations. */
+ private static final int EXIT_MIN_DELAY = 200;
+
+ /** Duration for animating between inside and outside touch. */
+ private static final int OUTSIDE_DURATION = 300;
+
+ /** Duration for animating pulses. */
+ private static final int PULSE_DURATION = 400;
+
+ /** Interval between pulses while inside and fully entered. */
+ private static final int PULSE_INTERVAL = 400;
+
+ /** Delay before pulses start. */
+ private static final int PULSE_DELAY = 500;
+
+ /** The target ripple being animated. */
+ private final Ripple mTarget;
+
+ /** When the ripple started appearing. */
+ private long mEnterTime = -1;
+
+ /** When the ripple started vanishing. */
+ private long mExitTime = -1;
+
+ /** When the ripple last transitioned between inside and outside touch. */
+ private long mOutsideTime = -1;
+
+ public RippleAnimator(Ripple target) {
+ mTarget = target;
+ }
+
+ /**
+ * Starts the enter animation.
+ */
+ public void enter() {
+ mEnterTime = AnimationUtils.currentAnimationTimeMillis();
+ }
+
+ /**
+ * Starts the exit animation. If {@link #enter()} was called recently, the
+ * animation may be postponed.
+ */
+ public void exit() {
+ final long minTime = mEnterTime + EXIT_MIN_DELAY;
+ mExitTime = Math.max(minTime, AnimationUtils.currentAnimationTimeMillis());
+ }
+
+ /**
+ * Starts the outside transition animation.
+ */
+ public void outside() {
+ mOutsideTime = AnimationUtils.currentAnimationTimeMillis();
+ }
+
+ /**
+ * Returns whether this ripple is currently animating.
+ */
+ public boolean isRunning() {
+ final long currentTime = AnimationUtils.currentAnimationTimeMillis();
+ return mEnterTime >= 0 && mEnterTime <= currentTime
+ && (mExitTime < 0 || currentTime <= mExitTime + EXIT_DURATION);
+ }
+
+ public void update() {
+ // Track three states:
+ // - Enter: touch begins, affects outer radius
+ // - Outside: touch moves outside bounds, affects maximum outer radius
+ // - Exit: touch ends, affects inner radius
+ final long currentTime = AnimationUtils.currentAnimationTimeMillis();
+ mTarget.mEnterState = mEnterTime < 0 ? 0 : INTERPOLATOR.getInterpolation(
+ MathUtils.constrain((currentTime - mEnterTime) / (float) ENTER_DURATION, 0, 1));
+ mTarget.mExitState = mExitTime < 0 ? 0 : INTERPOLATOR.getInterpolation(
+ MathUtils.constrain((currentTime - mExitTime) / (float) EXIT_DURATION, 0, 1));
+ mTarget.mOutsideState = mOutsideTime < 0 ? 1 : INTERPOLATOR.getInterpolation(
+ MathUtils.constrain((currentTime - mOutsideTime) / (float) OUTSIDE_DURATION, 0, 1));
+
+ // Pulse is a little more complicated.
+ final long pulseTime = (currentTime - mEnterTime - ENTER_DURATION - PULSE_DELAY);
+ mTarget.mPulseState = pulseTime < 0 ? -1
+ : (pulseTime % (PULSE_INTERVAL + PULSE_DURATION)) / (float) PULSE_DURATION;
+ }
+ }
}
diff --git a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
index 47a9374..64de95f 100644
--- a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
+++ b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
@@ -25,6 +25,7 @@
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
+import android.graphics.drawable.Ripple.RippleAnimator;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.os.SystemClock;
@@ -38,12 +39,17 @@
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
-import java.util.ArrayList;
/**
* Documentation pending.
*/
-public class TouchFeedbackDrawable extends DrawableWrapper {
+public class TouchFeedbackDrawable extends LayerDrawable {
+ private static final PorterDuffXfermode DST_ATOP = new PorterDuffXfermode(Mode.DST_ATOP);
+ private static final PorterDuffXfermode DST_IN = new PorterDuffXfermode(Mode.DST_IN);
+
+ /** The maximum number of ripples supported. */
+ private static final int MAX_RIPPLES = 10;
+
private final Rect mTempRect = new Rect();
private final Rect mPaddingRect = new Rect();
@@ -58,8 +64,9 @@
/** Lazily-created map of touch hotspot IDs to ripples. */
private SparseArray<Ripple> mTouchedRipples;
- /** Lazily-created list of actively animating ripples. */
- private ArrayList<Ripple> mActiveRipples;
+ /** Lazily-created array of actively animating ripples. */
+ private Ripple[] mActiveRipples;
+ private int mActiveRipplesCount = 0;
/** Lazily-created runnable for scheduling invalidation. */
private Runnable mAnimationRunnable;
@@ -76,50 +83,21 @@
/** Whether the animation runnable has been posted. */
private boolean mAnimating;
- /** The drawable to use as the mask. */
- private Drawable mMask;
-
TouchFeedbackDrawable() {
- this(new TouchFeedbackState(null), null, null);
- }
-
- private void setConstantState(TouchFeedbackState wrapperState, Resources res) {
- super.setConstantState(wrapperState, res);
-
- // Load a new mask drawable from the constant state.
- if (wrapperState == null || wrapperState.mMaskState == null) {
- mMask = null;
- } else if (res != null) {
- mMask = wrapperState.mMaskState.newDrawable(res);
- } else {
- mMask = wrapperState.mMaskState.newDrawable();
- }
-
- if (res != null) {
- mDensity = res.getDisplayMetrics().density;
- }
+ this(new TouchFeedbackState(null, null, null), null, null);
}
@Override
public int getOpacity() {
- return mActiveRipples != null && !mActiveRipples.isEmpty() ?
- PixelFormat.TRANSLUCENT : PixelFormat.TRANSPARENT;
- }
-
- @Override
- protected void onBoundsChange(Rect bounds) {
- super.onBoundsChange(bounds);
-
- if (mMask != null) {
- mMask.setBounds(bounds);
- }
+ // Worst-case scenario.
+ return PixelFormat.TRANSLUCENT;
}
@Override
protected boolean onStateChange(int[] stateSet) {
super.onStateChange(stateSet);
- if (mRipplePaint != null) {
+ if (mRipplePaint != null && mState.mTint != null) {
final ColorStateList stateList = mState.mTint;
final int newColor = stateList.getColorForState(stateSet, 0);
final int oldColor = mRipplePaint.getColor();
@@ -138,77 +116,39 @@
*/
@Override
public boolean isProjected() {
- return mState.mProjected;
+ return getNumberOfLayers() == 0;
}
@Override
public boolean isStateful() {
- return super.isStateful() || mState.mTint.isStateful();
+ return super.isStateful() || mState.mTint != null && mState.mTint.isStateful();
}
@Override
public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
throws XmlPullParserException, IOException {
- super.inflate(r, parser, attrs, theme);
-
final TypedArray a = obtainAttributes(
r, theme, attrs, R.styleable.TouchFeedbackDrawable);
- inflateStateFromTypedArray(r, a);
+ inflateStateFromTypedArray(a);
a.recycle();
-
- inflateChildElements(r, parser, attrs, theme);
+
+ super.inflate(r, parser, attrs, theme);
setTargetDensity(r.getDisplayMetrics());
}
-
- private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
- Theme theme) throws XmlPullParserException, IOException {
- int type;
- while ((type = parser.next()) == XmlPullParser.TEXT) {
- // Find the next non-text element.
- }
-
- if (type == XmlPullParser.START_TAG) {
- final Drawable dr = Drawable.createFromXmlInner(r, parser, attrs);
- setDrawable(dr, r);
- }
- }
-
- /**
- * Sets the wrapped drawable and update the constant state.
- *
- * @param drawable
- * @param res
- */
- void setMaskDrawable(Drawable drawable, Resources res) {
- mMask = drawable;
-
- if (drawable != null) {
- // Nobody cares if the mask has a callback.
- drawable.setCallback(null);
-
- mState.mMaskState = drawable.getConstantState();
- } else {
- mState.mMaskState = null;
- }
- }
/**
* Initializes the constant state from the values in the typed array.
*/
- private void inflateStateFromTypedArray(Resources r, TypedArray a) {
+ private void inflateStateFromTypedArray(TypedArray a) {
final TouchFeedbackState state = mState;
// Extract the theme attributes, if any.
final int[] themeAttrs = a.extractThemeAttrs();
- state.mThemeAttrs = themeAttrs;
+ state.mTouchThemeAttrs = themeAttrs;
if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_tint] == 0) {
mState.mTint = a.getColorStateList(R.styleable.TouchFeedbackDrawable_tint);
-
- if (mState.mTint == null) {
- throw new RuntimeException("<touch-feedback> tag requires a 'tint' attribute");
- }
}
if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_tintMode] == 0) {
@@ -219,34 +159,6 @@
if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_pinned] == 0) {
mState.mPinned = a.getBoolean(R.styleable.TouchFeedbackDrawable_pinned, false);
}
-
- Drawable mask = mMask;
- if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_mask] == 0) {
- mask = a.getDrawable(R.styleable.TouchFeedbackDrawable_mask);
- }
-
- Drawable dr = super.getDrawable();
- if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_drawable] == 0) {
- final int drawableRes = a.getResourceId(R.styleable.TouchFeedbackDrawable_drawable, 0);
- if (drawableRes != 0) {
- dr = r.getDrawable(drawableRes);
- }
- }
-
- // If neither a mask not a bottom layer was specified, assume we're
- // projecting onto a parent surface.
- mState.mProjected = mask == null && dr == null;
-
- if (dr != null) {
- setDrawable(dr, r);
- } else {
- // For now at least, we MUST have a wrapped drawable.
- setDrawable(new ColorDrawable(Color.TRANSPARENT), r);
- }
-
- if (mask != null) {
- setMaskDrawable(mask, r);
- }
}
/**
@@ -271,7 +183,7 @@
"Can't apply theme to <touch-feedback> with no constant state");
}
- final int[] themeAttrs = state.mThemeAttrs;
+ final int[] themeAttrs = state.mTouchThemeAttrs;
if (themeAttrs != null) {
final TypedArray a = t.resolveAttributes(
themeAttrs, R.styleable.TouchFeedbackDrawable, 0, 0);
@@ -298,39 +210,11 @@
if (a.hasValue(R.styleable.TouchFeedbackDrawable_pinned)) {
mState.mPinned = a.getBoolean(R.styleable.TouchFeedbackDrawable_pinned, false);
}
-
- Drawable mask = mMask;
- if (a.hasValue(R.styleable.TouchFeedbackDrawable_mask)) {
- mask = a.getDrawable(R.styleable.TouchFeedbackDrawable_mask);
- }
-
- Drawable dr = super.getDrawable();
- if (a.hasValue(R.styleable.TouchFeedbackDrawable_drawable)) {
- final int drawableRes = a.getResourceId(R.styleable.TouchFeedbackDrawable_drawable, 0);
- if (drawableRes != 0) {
- dr = a.getResources().getDrawable(drawableRes);
- }
- }
-
- // If neither a mask not a bottom layer was specified, assume we're
- // projecting onto a parent surface.
- mState.mProjected = mask == null && dr == null;
-
- if (dr != null) {
- setDrawable(dr, a.getResources());
- } else {
- // For now at least, we MUST have a wrapped drawable.
- setDrawable(new ColorDrawable(Color.TRANSPARENT), a.getResources());
- }
-
- if (mask != null) {
- setMaskDrawable(mask, a.getResources());
- }
}
@Override
public boolean canApplyTheme() {
- return mState != null && mState.mThemeAttrs != null;
+ return super.canApplyTheme() || mState != null && mState.mTouchThemeAttrs != null;
}
/**
@@ -351,7 +235,7 @@
public void setHotspot(int id, float x, float y) {
if (mTouchedRipples == null) {
mTouchedRipples = new SparseArray<Ripple>();
- mActiveRipples = new ArrayList<Ripple>();
+ mActiveRipples = new Ripple[MAX_RIPPLES];
}
final Ripple ripple = mTouchedRipples.get(id);
@@ -366,9 +250,9 @@
}
final Ripple newRipple = new Ripple(bounds, padding, x, y, mDensity);
- newRipple.enter();
+ newRipple.animate().enter();
- mActiveRipples.add(newRipple);
+ mActiveRipples[mActiveRipplesCount++] = newRipple;
mTouchedRipples.put(id, newRipple);
} else if (!mState.mPinned) {
ripple.move(x, y);
@@ -388,7 +272,7 @@
final Ripple ripple = mTouchedRipples.get(id);
if (ripple != null) {
- ripple.exit();
+ ripple.animate().exit();
mTouchedRipples.remove(id);
scheduleAnimation();
@@ -406,8 +290,7 @@
final int n = mTouchedRipples.size();
for (int i = 0; i < n; i++) {
- final Ripple ripple = mTouchedRipples.valueAt(i);
- ripple.exit();
+ mTouchedRipples.valueAt(i).animate().exit();
}
if (n > 0) {
@@ -420,7 +303,7 @@
* Schedules the next animation, if necessary.
*/
private void scheduleAnimation() {
- if (mActiveRipples == null || mActiveRipples.isEmpty()) {
+ if (mActiveRipplesCount == 0) {
mAnimating = false;
} else if (!mAnimating) {
mAnimating = true;
@@ -442,53 +325,68 @@
@Override
public void draw(Canvas canvas) {
- // The lower layer always draws normally.
- super.draw(canvas);
+ final boolean projected = getNumberOfLayers() == 0;
+ final Ripple[] activeRipples = mActiveRipples;
+ final int ripplesCount = mActiveRipplesCount;
+ final Rect bounds = getBounds();
- if (mActiveRipples == null || mActiveRipples.size() == 0) {
- // No ripples to draw.
- return;
- }
-
- final ArrayList<Ripple> activeRipples = mActiveRipples;
- final Drawable mask = mMask == null && !mState.mProjected ? getDrawable() : null;
- final Rect bounds = mask == null ? null : mask.getBounds();
-
- // Draw ripples into a layer that merges using SRC_IN.
- boolean hasRipples = false;
+ // Draw ripples.
+ boolean drewRipples = false;
int rippleRestoreCount = -1;
- int n = activeRipples.size();
- for (int i = 0; i < n; i++) {
- final Ripple ripple = activeRipples.get(i);
- if (!ripple.active()) {
- // TODO: Mark and sweep is more efficient.
- activeRipples.remove(i);
- i--;
- n--;
+ int activeRipplesCount = 0;
+ for (int i = 0; i < ripplesCount; i++) {
+ final Ripple ripple = activeRipples[i];
+ final RippleAnimator animator = ripple.animate();
+ animator.update();
+ if (!animator.isRunning()) {
+ activeRipples[i] = null;
} else {
- // If we're masking the ripple layer, make sure we have a layer first.
- if (mask != null && rippleRestoreCount < 0) {
+ // If we're masking the ripple layer, make sure we have a layer
+ // first. This will merge SRC_OVER (directly) onto the canvas.
+ if (!projected && rippleRestoreCount < 0) {
rippleRestoreCount = canvas.saveLayer(bounds.left, bounds.top,
- bounds.right, bounds.bottom, getMaskingPaint(SRC_ATOP), 0);
+ bounds.right, bounds.bottom, null, 0);
canvas.clipRect(bounds);
}
- hasRipples |= ripple.draw(canvas, getRipplePaint());
+ drewRipples |= ripple.draw(canvas, getRipplePaint());
+
+ activeRipples[activeRipplesCount] = activeRipples[i];
+ activeRipplesCount++;
+ }
+ }
+ mActiveRipplesCount = activeRipplesCount;
+
+ // TODO: Use the masking layer first, if there is one.
+
+ // If we have ripples and content, we need a masking layer. This will
+ // merge DST_ATOP onto (effectively under) the ripple layer.
+ if (drewRipples && !projected && rippleRestoreCount >= 0) {
+ canvas.saveLayer(bounds.left, bounds.top,
+ bounds.right, bounds.bottom, getMaskingPaint(DST_ATOP), 0);
+ }
+
+ Drawable mask = null;
+ final ChildDrawable[] array = mLayerState.mChildren;
+ final int N = mLayerState.mNum;
+ for (int i = 0; i < N; i++) {
+ if (array[i].mId != R.id.mask) {
+ array[i].mDrawable.draw(canvas);
+ } else {
+ mask = array[i].mDrawable;
}
}
// If we have ripples, mask them.
- if (mask != null && hasRipples) {
+ if (mask != null && drewRipples) {
+ // TODO: This will also mask the lower layer, which is bad.
canvas.saveLayer(bounds.left, bounds.top, bounds.right,
bounds.bottom, getMaskingPaint(DST_IN), 0);
mask.draw(canvas);
}
- // Composite the layers if needed:
- // 1. Mask DST_IN
- // 2. Ripples SRC_ATOP
- // 3. Lower n/a
- if (rippleRestoreCount > 0) {
+ // Composite the layers if needed.
+ if (rippleRestoreCount >= 0) {
canvas.restoreToCount(rippleRestoreCount);
}
}
@@ -497,15 +395,14 @@
if (mRipplePaint == null) {
mRipplePaint = new Paint();
mRipplePaint.setAntiAlias(true);
-
- final int color = mState.mTint.getColorForState(getState(), Color.TRANSPARENT);
- mRipplePaint.setColor(color);
+
+ if (mState.mTint != null) {
+ final int color = mState.mTint.getColorForState(getState(), Color.TRANSPARENT);
+ mRipplePaint.setColor(color);
+ }
}
return mRipplePaint;
}
-
- private static final PorterDuffXfermode SRC_ATOP = new PorterDuffXfermode(Mode.SRC_ATOP);
- private static final PorterDuffXfermode DST_IN = new PorterDuffXfermode(Mode.DST_IN);
private Paint getMaskingPaint(PorterDuffXfermode mode) {
if (mMaskingPaint == null) {
@@ -521,15 +418,12 @@
final Rect drawingBounds = mDrawingBounds;
dirtyBounds.set(drawingBounds);
drawingBounds.setEmpty();
-
final Rect rippleBounds = mTempRect;
- final ArrayList<Ripple> activeRipples = mActiveRipples;
- if (activeRipples != null) {
- final int N = activeRipples.size();
- for (int i = 0; i < N; i++) {
- activeRipples.get(i).getBounds(rippleBounds);
- drawingBounds.union(rippleBounds);
- }
+ final Ripple[] activeRipples = mActiveRipples;
+ final int N = mActiveRipplesCount;
+ for (int i = 0; i < N; i++) {
+ activeRipples[i].getBounds(rippleBounds);
+ drawingBounds.union(rippleBounds);
}
dirtyBounds.union(drawingBounds);
@@ -539,34 +433,30 @@
@Override
public ConstantState getConstantState() {
- // TODO: Can we just rely on super.getConstantState()?
return mState;
}
- static class TouchFeedbackState extends WrapperState {
- int[] mThemeAttrs;
- ConstantState mMaskState;
+ static class TouchFeedbackState extends LayerState {
+ int[] mTouchThemeAttrs;
ColorStateList mTint;
Mode mTintMode;
boolean mPinned;
- boolean mProjected;
- public TouchFeedbackState(TouchFeedbackState orig) {
- super(orig);
+ public TouchFeedbackState(
+ TouchFeedbackState orig, TouchFeedbackDrawable owner, Resources res) {
+ super(orig, owner, res);
if (orig != null) {
- mThemeAttrs = orig.mThemeAttrs;
+ mTouchThemeAttrs = orig.mTouchThemeAttrs;
mTint = orig.mTint;
mTintMode = orig.mTintMode;
- mMaskState = orig.mMaskState;
mPinned = orig.mPinned;
- mProjected = orig.mProjected;
}
}
@Override
public boolean canApplyTheme() {
- return mThemeAttrs != null;
+ return mTouchThemeAttrs != null || super.canApplyTheme();
}
@Override
@@ -586,13 +476,33 @@
}
private TouchFeedbackDrawable(TouchFeedbackState state, Resources res, Theme theme) {
- if (theme != null && state.canApplyTheme()) {
- mState = new TouchFeedbackState(state);
- applyTheme(theme);
+ boolean needsTheme = false;
+
+ final TouchFeedbackState ns;
+ if (theme != null && state != null && state.canApplyTheme()) {
+ ns = new TouchFeedbackState(state, this, res);
+ needsTheme = true;
+ } else if (state == null) {
+ ns = new TouchFeedbackState(null, this, res);
} else {
- mState = state;
+ ns = state;
}
- setConstantState(state, res);
+ if (res != null) {
+ mDensity = res.getDisplayMetrics().density;
+ }
+
+ mState = ns;
+ mLayerState = ns;
+
+ if (ns.mNum > 0) {
+ ensurePadding();
+ }
+
+ if (needsTheme) {
+ applyTheme(theme);
+ }
+
+ setPaddingMode(PADDING_MODE_STACK);
}
}
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
new file mode 100644
index 0000000..33683ab
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -0,0 +1,1967 @@
+/*
+ * 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.graphics.drawable;
+
+import android.animation.ArgbEvaluator;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.Resources.Theme;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.location.Address;
+import android.net.ParseException;
+import android.sax.StartElementListener;
+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;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+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 defined in an XML file with the <code><vector></code> element.
+ * <p/>
+ * The vector drawable has 6 elements:
+ * <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>
+ * <dd>Used to defined the intrinsic Width Height size of the drawable using
+ * <code>android:width</code> and <code>android:height</code> </dd>
+ * <dt><code><viewport></code></dt>
+ * <dd>Used to defined the size of the virtual canvas the paths are drawn on.
+ * 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>
+ * <dt><code><path></code></dt>
+ * <dd>Defines paths to be drawn. The path elements must be within a group
+ * <dl>
+ * <dt><code>android:name</code>
+ * <dd>Defines the name of the path.</dd></dt>
+ * <dt><code>android:pathData</code>
+ * <dd>Defines path string.</dd></dt>
+ * <dt><code>android:fill</code>
+ * <dd>Defines the color to fill the path (none if not present).</dd></dt>
+ * <dt><code>android:stroke</code>
+ * <dd>Defines the color to draw the path outline (none if not present).</dd></dt>
+ * <dt><code>android:strokeWidth</code>
+ * <dd>The width a path stroke</dd></dt>
+ * <dt><code>android:strokeOpacity</code>
+ * <dd>The opacity of a path stroke</dd></dt>
+ * <dt><code>android:rotation</code>
+ * <dd>The amount to rotation the path stroke.</dd></dt>
+ * <dt><code>android:pivotX</code>
+ * <dd>The X coordinate of the center of rotation of a path</dd></dt>
+ * <dt><code>android:pivotY</code>
+ * <dd>The Y coordinate of the center of rotation of a path</dd></dt>
+ * <dt><code>android:fillOpacity</code>
+ * <dd>The opacity to fill the path with</dd></dt>
+ * <dt><code>android:trimPathStart</code>
+ * <dd>The fraction of the path to trim from the start from 0 to 1</dd></dt>
+ * <dt><code>android:trimPathEnd</code>
+ * <dd>The fraction of the path to trim from the end from 0 to 1</dd></dt>
+ * <dt><code>android:trimPathOffset</code>
+ * <dd>Shift trim region (allows showed region to include the start and end) from 0 to 1</dd></dt>
+ * <dt><code>android:clipToPath</code>
+ * <dd>Path will set the clip path</dd></dt>
+ * <dt><code>android:strokeLineCap</code>
+ * <dd>Sets the linecap for a stroked path: butt, round, square</dd></dt>
+ * <dt><code>android:strokeLineJoin</code>
+ * <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>
+ */
+public class VectorDrawable extends Drawable {
+ private static final String LOGTAG = "VectorDrawable";
+ public static final int INFINITE = ValueAnimator.INFINITE;
+ private static final String SHAPE_SIZE = "size";
+ 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;
+ private static final int LINECAP_ROUND = 1;
+ private static final int LINECAP_SQUARE = 2;
+ private static final int LINEJOIN_MITER = 0;
+ 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 VectorDrawableState mVectorState;
+ private int mAlpha = 0xFF;
+
+ public VectorDrawable() {
+ mVectorState = new VectorDrawableState();
+ mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 1);
+ setDuration(DEFAULT_DURATION);
+ }
+
+ private VectorDrawable(VectorDrawableState state) {
+ mVectorState = new VectorDrawableState(state);
+ mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 1);
+ long duration = mVectorState.mVAnimatedPath.getTotalAnimationDuration();
+ if (duration == -1) { // if it set to infinite set to 1 hour
+ duration = DEFAULT_INFINITE_DURATION; // TODO define correct approach for infinite
+ mVectorState.mBasicAnimator.setFloatValues(0, duration / 1000);
+ mVectorState.mBasicAnimator.setInterpolator(new LinearInterpolator());
+ }
+ setDuration(duration);
+ }
+
+ final static class VectorDrawableState extends ConstantState {
+ int mChangingConfigurations;
+ ValueAnimator mBasicAnimator;
+ VAnimatedPath mVAnimatedPath = new VAnimatedPath();
+ Rect mPadding;
+ int mIntrinsicHeight;
+ int mIntrinsicWidth;
+
+ public VectorDrawableState(){
+ }
+
+ public VectorDrawableState(VectorDrawableState copy){
+ mChangingConfigurations = copy.mChangingConfigurations;
+ mVAnimatedPath = new VAnimatedPath(copy.mVAnimatedPath);
+ mPadding = new Rect(copy.mPadding);
+ mIntrinsicHeight = copy.mIntrinsicHeight;
+ mIntrinsicWidth = copy.mIntrinsicWidth;
+ }
+
+ @Override
+ public Drawable newDrawable() {
+ return new VectorDrawable(this);
+ }
+
+ @Override
+ public int getChangingConfigurations() {
+ return mChangingConfigurations;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see android.graphics.drawable.Drawable#getConstantState()
+ */
+ @Override
+ public ConstantState getConstantState() {
+ return mVectorState;
+ }
+
+ /**
+ * start the animation
+ */
+ public void start() {
+ mVectorState.mBasicAnimator.start();
+ }
+
+ /**
+ * Stop the animation.
+ */
+ public void stop() {
+ mVectorState.mBasicAnimator.end();
+ }
+
+ /**
+ * Get the current time point in the animation
+ *
+ * @return the current point on the animation
+ */
+ public float geAnimationFraction() {
+ return mVectorState.mVAnimatedPath.getValue();
+ }
+
+ /**
+ * set the time point in the animation
+ *
+ * @param value the point along the animation typically between 0 and 1
+ */
+ public void setAnimationFraction(float value) {
+ mVectorState.mVAnimatedPath.setAnimationFraction(value);
+ invalidateSelf();
+ }
+
+ /**
+ * set the amount of time the animation will take
+ *
+ * @param duration amount of time in milliseconds
+ */
+ public void setDuration(long duration) {
+ mVectorState.mBasicAnimator.setDuration(duration);
+ }
+
+ /**
+ * Defines what this animation should do when it reaches the end. This setting is applied only
+ * when the repeat count is either greater than 0 or {@link #INFINITE}.
+ */
+ public void setRepeatMode(int mode) {
+ mVectorState.mBasicAnimator.setRepeatMode(mode);
+ }
+
+ /**
+ * Sets animation to repeat
+ *
+ * @param repeat True if this drawable repeats its animation
+ */
+ public void setRepeatCount(int repeat) {
+ mVectorState.mBasicAnimator.setRepeatCount(repeat);
+ }
+
+ /**
+ * @return True if this drawable repeats its animation
+ */
+ public int getRepeatCount() {
+ return mVectorState.mBasicAnimator.getRepeatCount();
+ }
+
+ @Override
+ public boolean isStateful() {
+ return true;
+ }
+
+ @Override
+ protected boolean onStateChange(int[] state) {
+ mVectorState.mVAnimatedPath.setState(state);
+ int direction = mVectorState.mVAnimatedPath.getTrigger(state);
+ if (direction>0) {
+ animateForward();
+ } else if (direction<0) {
+ animateBackward();
+ }
+ super.onStateChange(state);
+ invalidateSelf();
+ return true;
+ }
+
+ private void animateForward(){
+ if (!mVectorState.mBasicAnimator.isStarted()) {
+ mVectorState.mBasicAnimator.setFloatValues(0,1);
+ start();
+ }
+ }
+
+ private void animateBackward(){
+ if (!mVectorState.mBasicAnimator.isStarted()) {
+ mVectorState.mBasicAnimator.setFloatValues(.99f,0);
+ start();
+ }
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ mVectorState.mVAnimatedPath.draw(canvas);
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ // TODO correct handling of transparent
+ if (mAlpha != alpha) {
+ mAlpha = alpha;
+ invalidateSelf();
+ }
+ }
+
+ /**
+ * Not implemented yet
+ * @hide
+ */
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ // TODO: support color filter
+ }
+
+ /**
+ * Returns a {@link android.graphics.PixelFormat graphics.PixelFormat}
+ * value of TRANSLUCENT.
+ */
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ /**
+ * Sets padding for this shape, defined by a Rect object. Define the padding in the Rect object
+ * as: left, top, right, bottom.
+ */
+ public void setPadding(Rect padding) {
+ setPadding(padding.left, padding.top, padding.right, padding.bottom);
+ }
+
+ /**
+ * Sets padding for the shape.
+ *
+ * @param left padding for the left side (in pixels)
+ * @param top padding for the top (in pixels)
+ * @param right padding for the right side (in pixels)
+ * @param bottom padding for the bottom (in pixels)
+ */
+ public void setPadding(int left, int top, int right, int bottom) {
+ if ((left | top | right | bottom) == 0) {
+ mVectorState.mPadding = null;
+ } else {
+ if (mVectorState.mPadding == null) {
+ mVectorState.mPadding = new Rect();
+ }
+ mVectorState.mPadding.set(left, top, right, bottom);
+ }
+ invalidateSelf();
+ }
+
+ /**
+ * Sets the intrinsic (default) width for this shape.
+ *
+ * @param width the intrinsic width (in pixels)
+ */
+ public void setIntrinsicWidth(int width) {
+ if (mVectorState.mIntrinsicWidth != width) {
+ mVectorState.mIntrinsicWidth = width;
+ invalidateSelf();
+ }
+ }
+
+ /**
+ * Sets the intrinsic (default) height for this shape.
+ *
+ * @param height the intrinsic height (in pixels)
+ */
+ public void setIntrinsicHeight(int height) {
+ if (mVectorState.mIntrinsicHeight != height) {
+ mVectorState.mIntrinsicHeight = height;
+ invalidateSelf();
+ }
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mVectorState.mIntrinsicWidth;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mVectorState.mIntrinsicHeight;
+ }
+
+ @Override
+ public boolean getPadding(Rect padding) {
+ if (mVectorState.mPadding != null) {
+ padding.set(mVectorState.mPadding);
+ return true;
+ } else {
+ return super.getPadding(padding);
+ }
+ }
+
+ /** @hide */
+ public static VectorDrawable create(Resources resources, int rid) {
+ try {
+ VectorDrawable drawable = new VectorDrawable();
+ XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ XmlPullParser xpp = resources.getXml(rid);
+ AttributeSet attrs = Xml.asAttributeSet(xpp);
+ drawable.inflate(resources, xpp, attrs);
+ drawable.setAnimationFraction(0);
+ return drawable;
+ } catch (XmlPullParserException e) {
+ Log.e(LOGTAG, "parser error", e);
+ } catch (IOException e) {
+ Log.e(LOGTAG, "parser error", e);
+ }
+ return null;
+ }
+
+ @Override
+ public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
+ throws XmlPullParserException, IOException {
+ setAnimatedPath(inflateInternal(res, parser, attrs));
+ }
+
+ private VAnimatedPath inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs)
+ throws XmlPullParserException, IOException {
+ boolean noSizeTag = true;
+ boolean noViewportTag = true;
+ boolean noGroupTag = true;
+ boolean noPathTag = true;
+ final VAnimatedPath animatedPath = new VAnimatedPath();
+ VectorDrawable.VGroup currentGroup = null;
+
+ int eventType = parser.getEventType();
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ String tagName = parser.getName();
+ if (SHAPE_PATH.equals(tagName)) {
+ VectorDrawable.VPath p = new VPath(res, attrs);
+ currentGroup.add(p);
+ noPathTag = false;
+ } else if (SHAPE_ANIMATION.equals(tagName)) {
+ VectorDrawable.VAnimation anim =
+ new VAnimation(res, attrs, animatedPath.mGroupList);
+ animatedPath.addAnimation(anim);
+ } else if (SHAPE_SIZE.equals(tagName)) {
+ animatedPath.parseSize(res, attrs);
+ noSizeTag = false;
+ } else if (SHAPE_VIEWPORT.equals(tagName)) {
+ animatedPath.parseViewport(res, attrs);
+ noViewportTag = false;
+ } else if (SHAPE_GROUP.equals(tagName)) {
+ currentGroup = new VectorDrawable.VGroup();
+ animatedPath.mGroupList.add(currentGroup);
+ noGroupTag = false;
+ } else if (SHAPE_VECTOR.equals(tagName)) {
+ 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".
+ // If the xml didn't specify the version number, the default version is "1".
+ int versionCode = a.getInt(R.styleable.VectorDrawable_versionCode, 1);
+ if (versionCode != 1) {
+ throw new IllegalArgumentException(
+ "So far, VectorDrawable only support version 1");
+ }
+
+ a.recycle();
+ }
+ }
+ eventType = parser.next();
+ }
+ if (noSizeTag || noViewportTag || noGroupTag || noPathTag) {
+ StringBuffer tag = new StringBuffer();
+ if (noSizeTag) {
+ tag.append("size");
+ }
+ if (noViewportTag){
+ if (tag.length()>0) {
+ tag.append(" & ");
+ }
+ tag.append("size");
+ }
+ if (noGroupTag){
+ if (tag.length()>0) {
+ tag.append(" & ");
+ }
+ tag.append("group");
+ }
+ if (noPathTag){
+ if (tag.length()>0) {
+ tag.append(" or ");
+ }
+ tag.append("path");
+ }
+ throw new XmlPullParserException("no "+tag+" defined");
+ }
+ // post parse cleanup
+ animatedPath.parseFinish();
+ return animatedPath;
+ }
+
+ private void setAnimatedPath(VAnimatedPath animatedPath) {
+ mVectorState.mVAnimatedPath = animatedPath;
+ setIntrinsicWidth((int) mVectorState.mVAnimatedPath.mBaseWidth);
+ setIntrinsicHeight((int) mVectorState.mVAnimatedPath.mBaseHeight);
+ long duration = mVectorState.mVAnimatedPath.getTotalAnimationDuration();
+ if (duration == -1) { // if it set to infinite set to 1 hour
+ duration = DEFAULT_INFINITE_DURATION; // TODO define correct approach for infinite
+ mVectorState.mBasicAnimator.setFloatValues(0, duration / 1000);
+ mVectorState.mBasicAnimator.setInterpolator(new LinearInterpolator());
+ }
+ setDuration(duration);
+
+ setAnimationFraction(0);
+ }
+
+ @Override
+ public boolean setVisible(boolean visible, boolean restart) {
+ boolean changed = super.setVisible(visible, restart);
+ if (visible) {
+ if (changed || restart) {
+ setAnimationFraction(0);
+ }
+ } else {
+ stop();
+ }
+ return changed;
+ }
+
+ private static class VAnimatedPath {
+ private static final String LOGTAG = "VAnimatedPath";
+
+ private ArrayList<VAnimation> mCurrentAnimList = null;
+ private VPath[] mCurrentPaths;
+ private float mAnimationValue = 0; // value goes from 0 to 1
+ private Paint mStrokePaint = null;
+ private Paint mFillPaint = null;
+ private PathMeasure mPathMeasure;
+ private Path mPath = new Path();
+ private Path mRenderPath = new Path();
+ private Matrix mMatrix = new Matrix();
+ private long mTotalDuration;
+ private int[] mCurrentState = new int[0];
+ private int mTrigger;
+ private boolean mTriggerState;
+ ArrayList<VGroup> mGroupList = new ArrayList<VGroup>();
+ float mBaseWidth = 1;
+ float mBaseHeight = 1;
+ float mViewportWidth;
+ float mViewportHeight;
+
+ public VAnimatedPath() {
+ setup();
+ }
+ public VAnimatedPath(VAnimatedPath copy) {
+ setup();
+ mCurrentAnimList = new ArrayList<VAnimation>(copy.mCurrentAnimList);
+ mGroupList = new ArrayList<VGroup>(copy.mGroupList);
+ if (copy.mCurrentPaths != null) {
+ mCurrentPaths = new VPath[copy.mCurrentPaths.length];
+ for (int i = 0; i < mCurrentPaths.length; i++) {
+ 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 void setTrigger(int trigger){
+ int []lut = { 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
+ };
+ mTrigger = lut[trigger];
+ }
+
+ private void setup(){
+ mStrokePaint = new Paint();
+ mStrokePaint.setStyle(Paint.Style.STROKE);
+ mStrokePaint.setAntiAlias(true);
+ mFillPaint = new Paint();
+ mFillPaint.setStyle(Paint.Style.FILL);
+ mFillPaint.setAntiAlias(true);
+ }
+
+ 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) {
+ int len = mCurrentPaths.length;
+ getTotalAnimationDuration();
+ long animationTime = (long) (value * mTotalDuration);
+
+ for (int i = 0; i < len; i++) {
+ VPath path = mCurrentPaths[i];
+ animationTime =
+ (long) ((mTotalDuration == -1) ? value * 1000 : mTotalDuration * value);
+ int size = mCurrentAnimList.size();
+ for (int j = 0; j < size; j++) {
+ VAnimation vAnimation = mCurrentAnimList.get(j);
+ if (vAnimation.doesAdjustPath(path)) {
+ mCurrentPaths[i] = vAnimation.getPathAtTime(animationTime, path);
+ }
+ }
+ }
+ this.mAnimationValue = value;
+ if (mTotalDuration == -1) {
+ return true;
+ } else {
+ return animationTime < mTotalDuration;
+ }
+ }
+
+ public void draw(Canvas canvas) {
+ int w = canvas.getWidth();
+ int h = canvas.getHeight();
+ float scale = w / mViewportWidth;
+ scale = Math.min(h / mViewportHeight, scale);
+
+ if (mCurrentPaths == null) {
+ Log.e(LOGTAG,"mCurrentPaths == null");
+ return;
+ }
+
+ for (int i = 0; i < mCurrentPaths.length; i++) {
+ if (mCurrentPaths[i] != null && mCurrentPaths[i].isVisible(mCurrentState)) {
+ drawPath(mCurrentPaths[i], canvas, w, h);
+ }
+ }
+ }
+
+ private void drawPath(VPath vPath, Canvas canvas, int w, int h) {
+ float scale = w / mViewportWidth;
+ scale = Math.min(h / mViewportHeight, scale);
+
+ vPath.toPath(mPath);
+ Path path = mPath;
+
+ if (vPath.mTrimPathStart != 0.0f || vPath.mTrimPathEnd != 1.0f) {
+ float start = (vPath.mTrimPathStart + vPath.mTrimPathOffset) % 1.0f;
+ float end = (vPath.mTrimPathEnd + vPath.mTrimPathOffset) % 1.0f;
+
+ if (mPathMeasure == null) {
+ mPathMeasure = new PathMeasure();
+ }
+ mPathMeasure.setPath(mPath, false);
+
+ float len = mPathMeasure.getLength();
+ start = start * len;
+ end = end * len;
+ path.reset();
+ if (start > end) {
+ mPathMeasure.getSegment(start, len, path, true);
+ mPathMeasure.getSegment(0f, end, path, true);
+ } else {
+ mPathMeasure.getSegment(start, end, path, true);
+ }
+ path.rLineTo(0, 0); // fix bug in measure
+ }
+
+ mRenderPath.reset();
+ mMatrix.reset();
+
+ mMatrix.postRotate(vPath.mRotate, vPath.mPivotX, vPath.mPivotY);
+ mMatrix.postScale(scale, scale, mViewportWidth / 2f, mViewportHeight / 2f);
+ mMatrix.postTranslate(w / 2f - mViewportWidth / 2f, h / 2f - mViewportHeight / 2f);
+
+ mRenderPath.addPath(path, mMatrix);
+
+ if (vPath.mClip) {
+ canvas.clipPath(mRenderPath, Region.Op.REPLACE);
+ }
+ if (vPath.mFillColor != 0) {
+ mFillPaint.setColor(vPath.mFillColor);
+ int alpha = 0xFF & (vPath.mFillColor >> 24);
+ mFillPaint.setAlpha(alpha);
+ canvas.drawPath(mRenderPath, mFillPaint);
+ }
+ if (vPath.mStrokeColor != 0) {
+ if (vPath.mStrokelineJoin != null) {
+ mStrokePaint.setStrokeJoin(vPath.mStrokelineJoin);
+ }
+ if (vPath.mStrokelineCap != null) {
+ mStrokePaint.setStrokeCap(vPath.mStrokelineCap);
+ }
+ mStrokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
+ mStrokePaint.setColor(vPath.mStrokeColor);
+ mStrokePaint.setAlpha(0xFF & (vPath.mStrokeColor >> 24));
+ mStrokePaint.setStrokeWidth(vPath.mStrokeWidth * scale);
+ canvas.drawPath(mRenderPath, mStrokePaint);
+ }
+ }
+
+ /**
+ * 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() {
+ 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());
+ Collection<VPath> paths = mGroupList.get(0).getPaths();
+ mCurrentPaths = paths.toArray(new VPath[paths.size()]);
+ for (int i = 0; i < mCurrentPaths.length; i++) {
+ mCurrentPaths[i] = new VPath(mCurrentPaths[i]);
+ }
+ }
+
+ 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 {
+ TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableViewport);
+ mViewportWidth = a.getFloat(R.styleable.VectorDrawableViewport_viewportWidth, 0);
+ mViewportHeight = a.getFloat(R.styleable.VectorDrawableViewport_viewportHeight, 0);
+ if (mViewportWidth == 0 || mViewportHeight == 0) {
+ throw new XmlPullParserException(a.getPositionDescription()+
+ "<viewport> tag requires viewportWidth & viewportHeight to be set");
+ }
+ a.recycle();
+ }
+
+ private void parseSize(Resources r, AttributeSet attrs)
+ throws XmlPullParserException {
+ TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableSize);
+ mBaseWidth = a.getDimension(R.styleable.VectorDrawableSize_width, 0);
+ mBaseHeight = a.getDimension(R.styleable.VectorDrawableSize_height, 0);
+ if (mBaseWidth == 0 || mBaseHeight == 0) {
+ throw new XmlPullParserException(a.getPositionDescription()+
+ "<size> tag requires width & height to be set");
+ }
+ a.recycle();
+ }
+ }
+
+ private static class VAnimation {
+ private static final String LOGTAG = "VAnimation";
+ private VPath[] mPaths = new VPath[0];
+
+ public enum Style {
+ INTERPOLATE, CROSSFADE, WIPE
+ }
+ Interpolator mAnimInterpolator = new AccelerateDecelerateInterpolator();
+ private Style mStyle;
+ private int mLimitProperty = 0;
+ private long[] mDuration = {DEFAULT_DURATION};
+ private long mStartOffset;
+ private long mRepeat = 1;
+ private HashSet<String>mSeqMap = new HashSet<String>();
+ private long mWipeDirection;
+ private int mMode = 0; // forward = 0 inAndOut = 1;
+ private int mInterpolatorType;
+ private String mId;
+ private final static int DIRECTION_FORWARD = 0;
+ private final static int DIRECTION_IN_AND_OUT = 1;
+
+ public VAnimation() {
+ }
+
+ public boolean doesAdjustPath(VPath path) {
+ return mSeqMap.contains(path.getID());
+ }
+
+ public VAnimation(Resources r, AttributeSet attrs, ArrayList<VGroup> groups)
+ throws XmlPullParserException {
+ String value;
+ String[] sp;
+ int name;
+
+ TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableAnimation);
+
+ value = a.getString(R.styleable.VectorDrawableAnimation_sequence);
+ if (value != null) {
+ sp = value.split(",");
+ VectorDrawable.VPath[] paths = new VectorDrawable.VPath[sp.length];
+
+ for (int j = 0; j < sp.length; j++) {
+ mSeqMap.add(sp[j].trim());
+ VectorDrawable.VPath path = groups.get(j).get(sp[j]);
+ path.mAnimated = true;
+ paths[j] = path;
+ }
+ setPaths(paths);
+ }
+
+ setLimitProperty(a.getInt(R.styleable.VectorDrawableAnimation_limitTo, 0));
+
+ name = R.styleable.VectorDrawableAnimation_durations;
+ value = a.getString(name);
+ if (value != null) {
+ long totalDuration = 0;
+ sp = value.split(",");
+ 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);
+ }
+
+ 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 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) {
+ this.mStyle = style;
+ }
+
+ public int getLimitProperty() {
+ return mLimitProperty;
+ }
+
+ public void setLimitProperty(int limitProperty) {
+ this.mLimitProperty = limitProperty;
+ }
+
+ public long[] getDuration() {
+ return mDuration;
+ }
+
+ public void setDuration(long[] duration) {
+ this.mDuration = duration;
+ }
+
+ public long getRepeat() {
+ return mRepeat;
+ }
+
+ public void setRepeat(long repeat) {
+ this.mRepeat = repeat;
+ }
+
+ public long getStartOffset() {
+ return mStartOffset;
+ }
+
+ public void setStartOffset(long startOffset) {
+ this.mStartOffset = startOffset;
+ }
+
+ public long getWipeDirection() {
+ return mWipeDirection;
+ }
+
+ public void setWipeDirection(long wipeDirection) {
+ this.mWipeDirection = wipeDirection;
+ }
+
+ public int getMode() {
+ return mMode;
+ }
+
+ public void setMode(int mode) {
+ this.mMode = mode;
+ }
+
+ public int getInterpolator() {
+ return mInterpolatorType;
+ }
+
+ public void setInterpolator(int interpolator) {
+ this.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) {
+ this.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) {
+ dest.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 {
+ private HashMap<String, VPath> mVGPathMap = new HashMap<String, VPath>();
+ private ArrayList<VPath> mVGList = new ArrayList<VPath>();
+
+ public void add(VPath path) {
+ String id = path.getID();
+ mVGPathMap.put(id, path);
+ mVGList.add(path);
+ }
+
+ public VPath get(String name) {
+ return mVGPathMap.get(name);
+ }
+
+ /**
+ * Must return in order of adding
+ * @return ordered list of paths
+ */
+ public Collection<VPath> getPaths() {
+ 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 VNode[] mNode = null;
+ private String mId;
+ int mStrokeColor = 0;
+ float mStrokeWidth = 0;
+ float mStrokeOpacity = Float.NaN;
+ int mFillColor = 0;
+ int mFillRule;
+ float mFillOpacity = Float.NaN;
+ float mRotate = 0;
+ float mPivotX = 0;
+ float mPivotY = 0;
+ float mTrimPathStart = 0;
+ float mTrimPathEnd = 1;
+ float mTrimPathOffset = 0;
+ boolean mAnimated = false;
+ boolean mClip = false;
+ public Paint.Cap mStrokelineCap = null;
+ public Paint.Join mStrokelineJoin = null;
+ float mStrokeMiterlimit = 4;
+ private int[] mCheckState = new int[MAX_STATES];
+ private boolean[] mCheckValue = new boolean[MAX_STATES];
+ private int mNumberOfStates = 0;
+ private int mNumberOfTrue = 0;
+
+ 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++;
+ }
+ }
+
+ 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) {
+ VNode.createPath(mNode, path);
+ }
+ }
+
+ public VPath() {
+ mId = this.toString(); // to ensure paths have unique names
+ }
+
+ public VPath(VPath p) {
+ copyFrom(p);
+ }
+
+ public String getID(){
+ return mId;
+ }
+
+ public VPath(Resources r, AttributeSet attrs) {
+ TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawablePath);
+ mClip = a.getBoolean(R.styleable.VectorDrawablePath_clipToPath, false);
+ mId = a.getString(R.styleable.VectorDrawablePath_name);
+ mNode = parsePath(a.getString(R.styleable.VectorDrawablePath_pathData));
+ mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, 0);
+ mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, Float.NaN);
+
+ if (!Float.isNaN(mFillOpacity)) {
+ mFillColor &= 0x00FFFFFF;
+ mFillColor |= ((int) (0xFF * mFillOpacity)) << 24;
+ }
+ mRotate = a.getFloat(R.styleable.VectorDrawablePath_rotation, 0);
+ mPivotX = a.getFloat(R.styleable.VectorDrawablePath_pivotX, 0);
+ mPivotY = a.getFloat(R.styleable.VectorDrawablePath_pivotY, 0);
+ int lineCap = a.getInt(R.styleable.VectorDrawablePath_strokeLineCap, 0);
+ switch (lineCap) {
+ case LINECAP_BUTT:
+ mStrokelineCap = Paint.Cap.BUTT;
+ break;
+ case LINECAP_ROUND:
+ mStrokelineCap = Paint.Cap.ROUND;
+ break;
+ case LINECAP_SQUARE:
+ mStrokelineCap = Paint.Cap.SQUARE;
+ break;
+ }
+ int lineJoin = a.getInt(R.styleable.VectorDrawablePath_strokeLineJoin, 0);
+ switch (lineJoin) {
+ case LINEJOIN_MITER:
+ mStrokelineJoin = Paint.Join.MITER;
+ break;
+ case LINEJOIN_ROUND:
+ mStrokelineJoin = Paint.Join.ROUND;
+ break;
+ case LINEJOIN_BEVEL:
+ mStrokelineJoin = Paint.Join.BEVEL;
+ break;
+ }
+ mStrokeMiterlimit = a.getFloat(R.styleable.VectorDrawablePath_strokeMiterLimit,
+ mStrokeMiterlimit);
+ mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_stroke, mStrokeColor);
+ mStrokeOpacity = a.getFloat(R.styleable.VectorDrawablePath_strokeOpacity, Float.NaN);
+ if (!Float.isNaN(mStrokeOpacity)) {
+ mStrokeColor &= 0x00FFFFFF;
+ mStrokeColor |= ((int) (0xFF * mStrokeOpacity)) << 24;
+ }
+ mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, 0);
+ mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, 1);
+ mTrimPathOffset = a.getFloat(R.styleable.VectorDrawablePath_trimPathOffset, 0);
+ mTrimPathStart = a.getFloat(R.styleable.VectorDrawablePath_trimPathStart, 0);
+ 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};
+ for (int state : states) {
+ if (a.hasValue(state)) {
+ addStateFilter(state, a.getBoolean(state, false));
+ }
+ }
+ a.recycle();
+ }
+
+ private static int nextStart(String s, int end) {
+ char c;
+
+ while (end < s.length()) {
+ c = s.charAt(end);
+ if (((c - 'A') * (c - 'Z') <= 0) || (((c - 'a') * (c - 'z') <= 0))) {
+ return end;
+ }
+ end++;
+ }
+ return end;
+ }
+
+ private void addNode(ArrayList<VectorDrawable.VNode> list, char cmd, float[] val) {
+ list.add(new VectorDrawable.VNode(cmd, val));
+ }
+
+ /**
+ * parse the floats in the string
+ * this is an optimized version of
+ * parseFloat(s.split(",|\\s"));
+ *
+ * @param s the string containing a command and list of floats
+ * @return array of floats
+ */
+ private static float[] getFloats(String s) {
+ if (s.charAt(0) == 'z' | s.charAt(0) == 'Z') {
+ return new float[0];
+ }
+ try {
+ float[] tmp = new float[s.length()];
+ int count = 0;
+ int pos = 1, end;
+ while ((end = extract(s, pos)) >= 0) {
+ if (pos < end) {
+ tmp[count++] = Float.parseFloat(s.substring(pos, end));
+ }
+ pos = end + 1;
+ }
+ // handle the final float if there is one
+ if (pos < s.length()) {
+ tmp[count++] = Float.parseFloat(s.substring(pos, s.length()));
+ }
+ return Arrays.copyOf(tmp, count);
+ } catch (NumberFormatException e){
+ Log.e(LOGTAG,"error in parsing \""+s+"\"");
+ throw e;
+ }
+ }
+
+ /**
+ * calculate the position of the next comma or space
+ * @param s the string to search
+ * @param start the position to start searching
+ * @return the position of the next comma or space or -1 if none found
+ */
+ private static int extract(String s, int start) {
+ int space = s.indexOf(' ', start);
+ int comma = s.indexOf(',', start);
+ if (space == -1) {
+ return comma;
+ }
+ if (comma == -1) {
+ return space;
+ }
+ return (comma > space) ? space : comma;
+ }
+
+ private VectorDrawable.VNode[] parsePath(String value) {
+ int start = 0;
+ int end = 1;
+
+ ArrayList<VectorDrawable.VNode> list = new ArrayList<VectorDrawable.VNode>();
+ while (end < value.length()) {
+ end = nextStart(value, end);
+ String s = value.substring(start, end);
+ float[] val = getFloats(s);
+ addNode(list, s.charAt(0), val);
+
+ start = end;
+ end++;
+ }
+ if ((end - start) == 1 && start < value.length()) {
+
+ addNode(list, value.charAt(start), new float[0]);
+ }
+ return list.toArray(new VectorDrawable.VNode[list.size()]);
+ }
+
+ public void copyFrom(VPath p1) {
+ mNode = new VNode[p1.mNode.length];
+ for (int i = 0; i < mNode.length; i++) {
+ mNode[i] = new VNode(p1.mNode[i]);
+ }
+ mId = p1.mId;
+ mStrokeColor = p1.mStrokeColor;
+ mFillColor = p1.mFillColor;
+ mStrokeWidth = p1.mStrokeWidth;
+ mRotate = p1.mRotate;
+ mPivotX = p1.mPivotX;
+ mPivotY = p1.mPivotY;
+ mAnimated = p1.mAnimated;
+ mTrimPathStart = p1.mTrimPathStart;
+ mTrimPathEnd = p1.mTrimPathEnd;
+ mTrimPathOffset = p1.mTrimPathOffset;
+ mStrokelineCap = p1.mStrokelineCap;
+ mStrokelineJoin = p1.mStrokelineJoin;
+ mStrokeMiterlimit = p1.mStrokeMiterlimit;
+ mNumberOfStates = p1.mNumberOfStates;
+ for (int i = 0; i < mNumberOfStates; i++) {
+ mCheckState[i] = p1.mCheckState[i];
+ mCheckValue[i] = p1.mCheckValue[i];
+ }
+
+ 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 t, int color1, int color2) {
+ int ret;
+ if (color1 == color2) {
+ return color2;
+ }
+ if (color1 == 0) {
+ return color2;
+ }
+ if (color2 == 0) {
+ return color1;
+ }
+
+ float t1 = 1 - t;
+ ret = 0xFF & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)));
+ color1 >>= 8;
+ color2 >>= 8;
+
+ ret |= 0xFF00 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 8);
+ color1 >>= 8;
+ color2 >>= 8;
+ ret |= 0xFF0000 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 16);
+ color1 >>= 8;
+ color2 >>= 8;
+ ret |= 0xFF000000 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 24);
+
+ return ret;
+ }
+
+ 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 {
+ char type;
+ float[] params;
+ private static float[] current = new float[4];
+ public VNode(char type, float[] params) {
+ this.type = type;
+ this.params = params;
+ }
+
+ public VNode(VNode n) {
+ this.type = n.type;
+ this.params = Arrays.copyOf(n.params, n.params.length);
+ }
+
+ public VNode(VNode n1, VNode n2, float t) {
+ this.type = n1.type;
+ this.params = new float[n1.params.length];
+ interpolate(n1, n2, t);
+ }
+
+ private boolean match(VNode n) {
+ if (n.type != type) {
+ return false;
+ }
+ return (params.length == n.params.length);
+ }
+
+ public void interpolate(VNode n1, VNode n2, float t) {
+ for (int i = 0; i < n1.params.length; i++) {
+ params[i] = n1.params[i] * (1 - t) + n2.params[i] * t;
+ }
+ }
+
+ private void nodeListToPath(VNode[] node, Path path) {
+ float[] current = new float[4];
+ for (int i = 0; i < node.length; i++) {
+ addCommand(path, current, node[i].type, node[i].params);
+ }
+ }
+
+ public static void createPath(VNode[] node, Path path) {
+ Arrays.fill(current,0);
+ for (int i = 0; i < node.length; i++) {
+ addCommand(path, current, node[i].type, node[i].params);
+ }
+ }
+
+ private static void addCommand(Path path, float[] current, char cmd, float[] val) {
+
+ int incr = 2;
+ float currentX = current[0];
+ float currentY = current[1];
+ float ctrlPointX = current[2];
+ float ctrlPointY = current[3];
+
+ switch (cmd) {
+ case 'z':
+ case 'Z':
+ path.close();
+ return;
+ case 'm':
+ case 'M':
+ case 'l':
+ case 'L':
+ case 't':
+ case 'T':
+ incr = 2;
+ break;
+ case 'h':
+ case 'H':
+ case 'v':
+ case 'V':
+ incr = 1;
+ break;
+ case 'c':
+ case 'C':
+ incr = 6;
+ break;
+ case 's':
+ case 'S':
+ case 'q':
+ case 'Q':
+ incr = 4;
+ break;
+ case 'a':
+ case 'A':
+ incr = 7;
+ 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]);
+ currentX += val[k + 0];
+ currentY += val[k + 1];
+ break;
+ case 'M': // moveto - Start a new sub-path
+ path.moveTo(val[k + 0], val[k + 1]);
+ currentX = val[k + 0];
+ currentY = val[k + 1];
+ break;
+ case 'l': // lineto - Draw a line from the current point (relative)
+ path.rLineTo(val[k + 0], val[k + 1]);
+ currentX += val[k + 0];
+ currentY += val[k + 1];
+ break;
+ case 'L': // lineto - Draw a line from the current point
+ path.lineTo(val[k + 0], val[k + 1]);
+ currentX = val[k + 0];
+ currentY = val[k + 1];
+ break;
+ case 'z': // closepath - Close the current subpath
+ case 'Z': // closepath - Close the current subpath
+ path.close();
+ break;
+ case 'h': // horizontal lineto - Draws a horizontal line (relative)
+ path.rLineTo(val[k + 0], 0);
+ currentX += val[k + 0];
+ break;
+ case 'H': // horizontal lineto - Draws a horizontal line
+ path.lineTo(val[k + 0], currentY);
+ currentX = val[k + 0];
+ break;
+ case 'v': // vertical lineto - Draws a vertical line from the current point (r)
+ path.rLineTo(0, val[k + 0]);
+ currentY += val[k + 0];
+ break;
+ case 'V': // vertical lineto - Draws a vertical line from the current point
+ path.lineTo(currentX, val[k + 0]);
+ currentY = val[k + 0];
+ break;
+ case 'c': // curveto - Draws a cubic Bézier curve (relative)
+ path.rCubicTo(val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3],
+ val[k + 4],
+ val[k + 5]);
+
+ ctrlPointX = currentX + val[k + 2];
+ ctrlPointY = currentY + val[k + 3];
+ currentX += val[k + 4];
+ currentY += val[k + 5];
+
+ break;
+ case 'C': // curveto - Draws a cubic Bézier curve
+ path.cubicTo(val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3],
+ val[k + 4],
+ val[k + 5]);
+ currentX = val[k + 4];
+ currentY = val[k + 5];
+ ctrlPointX = val[k + 2];
+ ctrlPointY = val[k + 3];
+
+ break;
+ case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
+ path.rCubicTo(currentX - ctrlPointX, currentY - ctrlPointY,
+ val[k + 0], val[k + 1],
+ val[k + 2], val[k + 3]);
+
+ ctrlPointX = currentX + val[k + 0];
+ ctrlPointY = currentY + val[k + 1];
+ currentX += val[k + 2];
+ currentY += val[k + 3];
+ break;
+ case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
+ path.cubicTo(2 * currentX - ctrlPointX,
+ 2 * currentY - ctrlPointY,
+ val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3]);
+ currentX = val[k + 2];
+ currentY = val[k + 3];
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ break;
+ case 'q': // Draws a quadratic Bézier (relative)
+ path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ currentX += val[k + 2];
+ currentY += val[k + 3];
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ break;
+ case 'Q': // Draws a quadratic Bézier
+ path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ currentX = val[k + 2];
+ currentY = val[k + 3];
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ break;
+ case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
+ path.rQuadTo(currentX - ctrlPointX, currentY - ctrlPointY,
+ val[k + 0], val[k + 1]);
+ ctrlPointX = ctrlPointX + currentX;
+ ctrlPointY = ctrlPointY + currentY;
+ currentX += val[k + 0];
+ currentY += val[k + 1];
+
+ break;
+ case 'T': // Draws a quadratic Bézier curve (reflective control point)
+ path.quadTo(currentX * 2 - ctrlPointX, currentY * 2 - ctrlPointY,
+ val[k + 0], val[k + 1]);
+ currentX = val[k + 0];
+ currentY = val[k + 1]; // TODO: Check this logic
+ ctrlPointX = -(val[k + 0] - currentX);
+ ctrlPointY = -(val[k + 1] - currentY);
+ break;
+ case 'a': // Draws an elliptical arc
+ // (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
+ drawArc(path,
+ currentX,
+ currentY,
+ val[k + 5] + currentX,
+ val[k + 6] + currentY,
+ val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3] != 0,
+ val[k + 4] != 0);
+ currentX += val[k + 5];
+ currentY += val[k + 6];
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
+
+ break;
+ case 'A': // Draws an elliptical arc
+ drawArc(path,
+ currentX,
+ currentY,
+ val[k + 5],
+ val[k + 6],
+ val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3] != 0,
+ val[k + 4] != 0);
+ currentX = val[k + 5];
+ currentY = val[k + 6];
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
+ break;
+ }
+ }
+ current[0] = currentX;
+ current[1] = currentY;
+ current[2] = ctrlPointX;
+ current[3] = ctrlPointY;
+ }
+
+ private static void drawArc(Path p,
+ float x0,
+ float y0,
+ float x1,
+ float y1,
+ float a,
+ float b,
+ float theta,
+ boolean isMoreThanHalf,
+ boolean isPositiveArc) {
+
+ /* Convert rotation angle from degrees to radians */
+ double thetaD = Math.toRadians(theta);
+ /* Pre-compute rotation matrix entries */
+ double cosTheta = Math.cos(thetaD);
+ double sinTheta = Math.sin(thetaD);
+ /* Transform (x0, y0) and (x1, y1) into unit space */
+ /* using (inverse) rotation, followed by (inverse) scale */
+ double x0p = (x0 * cosTheta + y0 * sinTheta) / a;
+ double y0p = (-x0 * sinTheta + y0 * cosTheta) / b;
+ double x1p = (x1 * cosTheta + y1 * sinTheta) / a;
+ double y1p = (-x1 * sinTheta + y1 * cosTheta) / b;
+
+ /* Compute differences and averages */
+ double dx = x0p - x1p;
+ double dy = y0p - y1p;
+ double xm = (x0p + x1p) / 2;
+ double ym = (y0p + y1p) / 2;
+ /* Solve for intersecting unit circles */
+ double dsq = dx * dx + dy * dy;
+ if (dsq == 0.0) {
+ Log.w(LOGTAG, " Points are coincident");
+ return; /* Points are coincident */
+ }
+ double disc = 1.0 / dsq - 1.0 / 4.0;
+ if (disc < 0.0) {
+ Log.w(LOGTAG, "Points are too far apart " + dsq);
+ float adjust = (float) (Math.sqrt(dsq) / 1.99999);
+ drawArc(p, x0, y0, x1, y1, a * adjust,
+ b * adjust, theta, isMoreThanHalf, isPositiveArc);
+ return; /* Points are too far apart */
+ }
+ double s = Math.sqrt(disc);
+ double sdx = s * dx;
+ double sdy = s * dy;
+ double cx;
+ double cy;
+ if (isMoreThanHalf == isPositiveArc) {
+ cx = xm - sdy;
+ cy = ym + sdx;
+ } else {
+ cx = xm + sdy;
+ cy = ym - sdx;
+ }
+
+ double eta0 = Math.atan2((y0p - cy), (x0p - cx));
+
+ double eta1 = Math.atan2((y1p - cy), (x1p - cx));
+
+ double sweep = (eta1 - eta0);
+ if (isPositiveArc != (sweep >= 0)) {
+ if (sweep > 0) {
+ sweep -= 2 * Math.PI;
+ } else {
+ sweep += 2 * Math.PI;
+ }
+ }
+
+ cx *= a;
+ cy *= b;
+ double tcx = cx;
+ cx = cx * cosTheta - cy * sinTheta;
+ cy = tcx * sinTheta + cy * cosTheta;
+
+ arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep);
+ }
+
+ /**
+ * Converts an arc to cubic Bezier segments and records them in p.
+ *
+ * @param p The target for the cubic Bezier segments
+ * @param cx The x coordinate center of the ellipse
+ * @param cy The y coordinate center of the ellipse
+ * @param a The radius of the ellipse in the horizontal direction
+ * @param b The radius of the ellipse in the vertical direction
+ * @param e1x E(eta1) x coordinate of the starting point of the arc
+ * @param e1y E(eta2) y coordinate of the starting point of the arc
+ * @param theta The angle that the ellipse bounding rectangle makes with horizontal plane
+ * @param start The start angle of the arc on the ellipse
+ * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
+ */
+ private static void arcToBezier(Path p,
+ double cx,
+ double cy,
+ double a,
+ double b,
+ double e1x,
+ double e1y,
+ double theta,
+ double start,
+ double sweep) {
+ // Taken from equations at: http://spaceroots.org/documents/ellipse/node8.html
+ // and http://www.spaceroots.org/documents/ellipse/node22.html
+
+ // Maximum of 45 degrees per cubic Bezier segment
+ int numSegments = Math.abs((int) Math.ceil(sweep * 4 / Math.PI));
+
+ double eta1 = start;
+ double cosTheta = Math.cos(theta);
+ double sinTheta = Math.sin(theta);
+ double cosEta1 = Math.cos(eta1);
+ double sinEta1 = Math.sin(eta1);
+ double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1);
+ double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1);
+
+ double anglePerSegment = sweep / numSegments;
+ for (int i = 0; i < numSegments; i++) {
+ double eta2 = eta1 + anglePerSegment;
+ double sinEta2 = Math.sin(eta2);
+ double cosEta2 = Math.cos(eta2);
+ double e2x = cx + (a * cosTheta * cosEta2) - (b * sinTheta * sinEta2);
+ double e2y = cy + (a * sinTheta * cosEta2) + (b * cosTheta * sinEta2);
+ double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2;
+ double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2;
+ double tanDiff2 = Math.tan((eta2 - eta1) / 2);
+ double alpha =
+ Math.sin(eta2 - eta1) * (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3;
+ double q1x = e1x + alpha * ep1x;
+ double q1y = e1y + alpha * ep1y;
+ double q2x = e2x - alpha * ep2x;
+ double q2y = e2y - alpha * ep2y;
+
+ p.cubicTo((float) q1x,
+ (float) q1y,
+ (float) q2x,
+ (float) q2y,
+ (float) e2x,
+ (float) e2y);
+ eta1 = eta2;
+ e1x = e2x;
+ e1y = e2y;
+ ep1x = ep2x;
+ ep1y = ep2y;
+ }
+ }
+
+ }
+}
diff --git a/include/android_runtime/AndroidRuntime.h b/include/android_runtime/AndroidRuntime.h
index 649f4c3..6f2af90 100644
--- a/include/android_runtime/AndroidRuntime.h
+++ b/include/android_runtime/AndroidRuntime.h
@@ -34,7 +34,7 @@
class AndroidRuntime
{
public:
- AndroidRuntime();
+ AndroidRuntime(char* argBlockStart, size_t argBlockSize);
virtual ~AndroidRuntime();
enum StartMode {
@@ -44,6 +44,8 @@
Tool,
};
+ void setArgv0(const char* argv0);
+
/**
* Register a set of methods in the specified class.
*/
@@ -120,6 +122,8 @@
Vector<JavaVMOption> mOptions;
bool mExitWithoutCleanup;
+ char* const mArgBlockStart;
+ const size_t mArgBlockLength;
/* JNI JavaVM pointer */
static JavaVM* mJavaVM;
diff --git a/include/androidfw/AssetManager.h b/include/androidfw/AssetManager.h
index a13dd16..610528c 100644
--- a/include/androidfw/AssetManager.h
+++ b/include/androidfw/AssetManager.h
@@ -161,7 +161,7 @@
* path hierarchy, and will not be seen by "AssetDir" or included
* in our filename cache.
*/
- Asset* openNonAsset(const char* fileName, AccessMode mode);
+ Asset* openNonAsset(const char* fileName, AccessMode mode, int32_t* outCookie = NULL);
/*
* Explicit non-asset file. The file explicitly named by the cookie (the
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index b334aab..7cc10be87 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -25,6 +25,7 @@
#include <utils/Errors.h>
#include <utils/String16.h>
#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
#include <utils/threads.h>
@@ -216,7 +217,8 @@
// Chunk types in RES_TABLE_TYPE
RES_TABLE_PACKAGE_TYPE = 0x0200,
RES_TABLE_TYPE_TYPE = 0x0201,
- RES_TABLE_TYPE_SPEC_TYPE = 0x0202
+ RES_TABLE_TYPE_SPEC_TYPE = 0x0202,
+ RES_TABLE_LIBRARY_TYPE = 0x0203
};
/**
@@ -268,6 +270,9 @@
// The 'data' holds a complex number encoding a fraction of a
// container.
TYPE_FRACTION = 0x06,
+ // The 'data' holds a dynamic ResTable_ref, which needs to be
+ // resolved before it can be used like a TYPE_REFERENCE.
+ TYPE_DYNAMIC_REFERENCE = 0x07,
// Beginning of integer flavors...
TYPE_FIRST_INT = 0x10,
@@ -457,6 +462,7 @@
ResStringPool(const void* data, size_t size, bool copyData=false);
~ResStringPool();
+ void setToEmpty();
status_t setTo(const void* data, size_t size, bool copyData=false);
status_t getError() const;
@@ -735,14 +741,16 @@
const void* mCurExt;
};
+class DynamicRefTable;
+
/**
* Convenience class for accessing data in a ResXMLTree resource.
*/
class ResXMLTree : public ResXMLParser
{
public:
+ ResXMLTree(const DynamicRefTable* dynamicRefTable);
ResXMLTree();
- ResXMLTree(const void* data, size_t size, bool copyData=false);
~ResXMLTree();
status_t setTo(const void* data, size_t size, bool copyData=false);
@@ -756,6 +764,8 @@
status_t validateNode(const ResXMLTree_node* node) const;
+ const DynamicRefTable* const mDynamicRefTable;
+
status_t mError;
void* mOwnedData;
const ResXMLTree_header* mHeader;
@@ -1290,6 +1300,7 @@
struct ResTable_map_entry : public ResTable_entry
{
// Resource identifier of the parent mapping, or 0 if there is none.
+ // This is always treated as a TYPE_DYNAMIC_REFERENCE.
ResTable_ref parent;
// Number of name/value pairs that follow for FLAG_COMPLEX.
uint32_t count;
@@ -1385,6 +1396,68 @@
};
/**
+ * A package-id to package name mapping for any shared libraries used
+ * in this resource table. The package-id's encoded in this resource
+ * table may be different than the id's assigned at runtime. We must
+ * be able to translate the package-id's based on the package name.
+ */
+struct ResTable_lib_header
+{
+ struct ResChunk_header header;
+
+ // The number of shared libraries linked in this resource table.
+ uint32_t count;
+};
+
+/**
+ * A shared library package-id to package name entry.
+ */
+struct ResTable_lib_entry
+{
+ // The package-id this shared library was assigned at build time.
+ // We use a uint32 to keep the structure aligned on a uint32 boundary.
+ uint32_t packageId;
+
+ // The package name of the shared library. \0 terminated.
+ char16_t packageName[128];
+};
+
+/**
+ * Holds the shared library ID table. Shared libraries are assigned package IDs at
+ * build time, but they may be loaded in a different order, so we need to maintain
+ * a mapping of build-time package ID to run-time assigned package ID.
+ *
+ * Dynamic references are not currently supported in overlays. Only the base package
+ * may have dynamic references.
+ */
+class DynamicRefTable
+{
+public:
+ DynamicRefTable(uint8_t packageId);
+
+ // Loads an unmapped reference table from the package.
+ status_t load(const ResTable_lib_header* const header);
+
+ // Creates a mapping from build-time package ID to run-time package ID for
+ // the given package.
+ status_t addMapping(const String16& packageName, uint8_t packageId);
+
+ // Performs the actual conversion of build-time resource ID to run-time
+ // resource ID.
+ inline status_t lookupResourceId(uint32_t* resId) const;
+ inline status_t lookupResourceValue(Res_value* value) const;
+
+ inline const KeyedVector<String16, uint8_t>& entries() const {
+ return mEntries;
+ }
+
+private:
+ const uint8_t mAssignedPackageId;
+ uint8_t mLookupTable[256];
+ KeyedVector<String16, uint8_t> mEntries;
+};
+
+/**
* Convenience class for accessing data in a ResTable resource.
*/
class ResTable
@@ -1399,6 +1472,7 @@
const void* idmap = NULL);
status_t add(const void *data, size_t size);
status_t add(ResTable* src);
+ status_t addEmpty(const int32_t cookie);
status_t getError() const;
@@ -1634,7 +1708,7 @@
bool append = false);
size_t getBasePackageCount() const;
- const char16_t* getBasePackageName(size_t idx) const;
+ const String16 getBasePackageName(size_t idx) const;
uint32_t getBasePackageId(size_t idx) const;
// Return the number of resource tables that the object contains.
@@ -1647,6 +1721,8 @@
// Return unique cookie identifier for the given resource table.
int32_t getTableCookie(size_t index) const;
+ const DynamicRefTable* getDynamicRefTableForCookie(int32_t cookie) const;
+
// Return the configurations (ResTable_config) that we know about
void getConfigurations(Vector<ResTable_config>* configs) const;
@@ -1684,7 +1760,7 @@
struct bag_set;
status_t addInternal(const void* data, size_t size, const int32_t cookie,
- Asset* asset, bool copyData, const Asset* idmap);
+ bool copyData, const Asset* idmap);
ssize_t getResourcePackageIndex(uint32_t resID) const;
ssize_t getEntry(
@@ -1712,6 +1788,8 @@
// Mapping from resource package IDs to indices into the internal
// package array.
uint8_t mPackageMap[256];
+
+ uint8_t mNextPackageId;
};
} // namespace android
diff --git a/include/private/hwui/DrawGlInfo.h b/include/private/hwui/DrawGlInfo.h
index fc810be..a357a01 100644
--- a/include/private/hwui/DrawGlInfo.h
+++ b/include/private/hwui/DrawGlInfo.h
@@ -55,7 +55,10 @@
kModeDraw,
// Indicates the the functor is called only to perform
// processing and that no draw should be attempted
- kModeProcess
+ kModeProcess,
+ // Same as kModeProcess, however there is no GL context because it was
+ // lost or destroyed
+ kModeProcessNoContext
};
/**
@@ -65,14 +68,6 @@
enum Status {
// The functor is done
kStatusDone = 0x0,
- // The functor is requesting a redraw (the clip rect
- // used by the redraw is specified by DrawGlInfo.)
- // The rest of the UI might redraw too.
- kStatusDraw = 0x1,
- // The functor needs to be invoked again but will
- // not redraw. Only the functor is invoked again
- // (unless another functor requests a redraw.)
- kStatusInvoke = 0x2,
// DisplayList actually issued GL drawing commands.
// This is used to signal the HardwareRenderer that the
// buffers should be flipped - otherwise, there were no
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 64363d4..91dda75 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -74,6 +74,7 @@
static const char* kAppZipName = NULL; //"classes.jar";
static const char* kSystemAssets = "framework/framework-res.apk";
static const char* kResourceCache = "resource-cache";
+static const char* kAndroidManifest = "AndroidManifest.xml";
static const char* kExcludeExtension = ".EXCLUDE";
@@ -205,6 +206,16 @@
ALOGV("In %p Asset %s path: %s", this,
ap.type == kFileTypeDirectory ? "dir" : "zip", ap.path.string());
+ // Check that the path has an AndroidManifest.xml
+ Asset* manifestAsset = const_cast<AssetManager*>(this)->openNonAssetInPathLocked(
+ kAndroidManifest, Asset::ACCESS_BUFFER, ap);
+ if (manifestAsset == NULL) {
+ // This asset path does not contain any resources.
+ delete manifestAsset;
+ return false;
+ }
+ delete manifestAsset;
+
mAssetPaths.add(ap);
// new paths are always added at the end
@@ -461,7 +472,7 @@
* The "fileName" is the partial path starting from the application
* name.
*/
-Asset* AssetManager::openNonAsset(const char* fileName, AccessMode mode)
+Asset* AssetManager::openNonAsset(const char* fileName, AccessMode mode, int32_t* outCookie)
{
AutoMutex _l(mLock);
@@ -482,6 +493,7 @@
Asset* pAsset = openNonAssetInPathLocked(
fileName, mode, mAssetPaths.itemAt(i));
if (pAsset != NULL) {
+ if (outCookie != NULL) *outCookie = static_cast<int32_t>(i + 1);
return pAsset != kExcludedAsset ? pAsset : NULL;
}
}
@@ -556,9 +568,14 @@
LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager");
}
- if (mCacheMode != CACHE_OFF && !mCacheValid)
+ if (mCacheMode != CACHE_OFF && !mCacheValid) {
const_cast<AssetManager*>(this)->loadFileNameCacheLocked();
+ }
+ mResources = new ResTable();
+ updateResourceParamsLocked();
+
+ bool onlyEmptyResources = true;
const size_t N = mAssetPaths.size();
for (size_t i=0; i<N; i++) {
Asset* ass = NULL;
@@ -621,35 +638,39 @@
ap);
shared = false;
}
+
if ((ass != NULL || sharedRes != NULL) && ass != kExcludedAsset) {
- if (rt == NULL) {
- mResources = rt = new ResTable();
- updateResourceParamsLocked();
- }
ALOGV("Installing resource asset %p in to table %p\n", ass, mResources);
if (sharedRes != NULL) {
ALOGV("Copying existing resources for %s", ap.path.string());
- rt->add(sharedRes);
+ mResources->add(sharedRes);
} else {
ALOGV("Parsing resources for %s", ap.path.string());
- rt->add(ass, i + 1, !shared, idmap);
+ mResources->add(ass, i + 1, !shared, idmap);
}
+ onlyEmptyResources = false;
if (!shared) {
delete ass;
}
+ } else {
+ ALOGW("Installing empty resources in to table %p\n", mResources);
+ mResources->addEmpty(i + 1);
}
+
if (idmap != NULL) {
delete idmap;
}
MY_TRACE_END();
}
- if (required && !rt) ALOGW("Unable to find resources file resources.arsc");
- if (!rt) {
- mResources = rt = new ResTable();
+ if (required && onlyEmptyResources) {
+ ALOGW("Unable to find resources file resources.arsc");
+ delete mResources;
+ mResources = NULL;
}
- return rt;
+
+ return mResources;
}
void AssetManager::updateResourceParamsLocked() const
diff --git a/libs/androidfw/BackupData.cpp b/libs/androidfw/BackupData.cpp
index a5b9416..d16d5498 100644
--- a/libs/androidfw/BackupData.cpp
+++ b/libs/androidfw/BackupData.cpp
@@ -79,7 +79,7 @@
paddingSize = padding_extra(n);
if (paddingSize > 0) {
uint32_t padding = 0xbcbcbcbc;
- if (DEBUG) ALOGI("writing %d padding bytes for %d", paddingSize, n);
+ if (DEBUG) ALOGI("writing %zd padding bytes for %d", paddingSize, n);
amt = write(m_fd, &padding, paddingSize);
if (amt != paddingSize) {
m_status = errno;
@@ -113,7 +113,7 @@
k = key;
}
if (DEBUG) {
- ALOGD("Writing header: prefix='%s' key='%s' dataSize=%d", m_keyPrefix.string(),
+ ALOGD("Writing header: prefix='%s' key='%s' dataSize=%zu", m_keyPrefix.string(),
key.string(), dataSize);
}
@@ -126,7 +126,7 @@
header.keyLen = tolel(keyLen);
header.dataSize = tolel(dataSize);
- if (DEBUG) ALOGI("writing entity header, %d bytes", sizeof(entity_header_v1));
+ if (DEBUG) ALOGI("writing entity header, %zu bytes", sizeof(entity_header_v1));
amt = write(m_fd, &header, sizeof(entity_header_v1));
if (amt != sizeof(entity_header_v1)) {
m_status = errno;
@@ -134,7 +134,7 @@
}
m_pos += amt;
- if (DEBUG) ALOGI("writing entity header key, %d bytes", keyLen+1);
+ if (DEBUG) ALOGI("writing entity header key, %zd bytes", keyLen+1);
amt = write(m_fd, k.string(), keyLen+1);
if (amt != keyLen+1) {
m_status = errno;
diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp
index ab837ad..52dce9f 100644
--- a/libs/androidfw/BackupHelpers.cpp
+++ b/libs/androidfw/BackupHelpers.cpp
@@ -639,7 +639,7 @@
// size header -- calc len in digits by actually rendering the number
// to a string - brute force but simple
- snprintf(sizeStr, sizeof(sizeStr), "%lld", s.st_size);
+ snprintf(sizeStr, sizeof(sizeStr), "%lld", (long long)s.st_size);
p += write_pax_header_entry(p, "size", sizeStr);
// fullname was generated above with the ustar paths
@@ -661,7 +661,7 @@
// [ 124 : 12 ] size of pax extended header data
memset(paxHeader + 124, 0, 12);
- snprintf(paxHeader + 124, 12, "%011o", p - paxData);
+ snprintf(paxHeader + 124, 12, "%011o", (unsigned int)(p - paxData));
// Checksum and write the pax block header
calc_tar_checksum(paxHeader);
@@ -681,7 +681,10 @@
if (!isdir) {
off64_t toWrite = s.st_size;
while (toWrite > 0) {
- size_t toRead = (toWrite < BUFSIZE) ? toWrite : BUFSIZE;
+ size_t toRead = toWrite;
+ if (toRead > BUFSIZE) {
+ toRead = BUFSIZE;
+ }
ssize_t nRead = read(fd, buf, toRead);
if (nRead < 0) {
err = errno;
@@ -1095,8 +1098,8 @@
if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
|| states[i].modTime_nsec != state.modTime_nsec || states[i].mode != state.mode
|| states[i].size != state.size || states[i].crc32 != states[i].crc32) {
- fprintf(stderr, "state %zu expected={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n"
- " actual={%d/%d, 0x%08x, %04o, 0x%08x, %3zu} '%s'\n", i,
+ fprintf(stderr, "state %zu expected={%d/%d, %04o, 0x%08x, 0x%08x, %3zu} '%s'\n"
+ " actual={%d/%d, %04o, 0x%08x, 0x%08x, %3d} '%s'\n", i,
states[i].modTime_sec, states[i].modTime_nsec, states[i].mode, states[i].size,
states[i].crc32, name.length(), filenames[i].string(),
state.modTime_sec, state.modTime_nsec, state.mode, state.size, state.crc32,
@@ -1194,7 +1197,7 @@
test_read_header_and_entity(BackupDataReader& reader, const char* str)
{
int err;
- int bufSize = strlen(str)+1;
+ size_t bufSize = strlen(str)+1;
char* buf = (char*)malloc(bufSize);
String8 string;
int cookie = 0x11111111;
@@ -1229,9 +1232,9 @@
err = EINVAL;
goto finished;
}
- if ((int)actualSize != bufSize) {
- fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08zx\n", bufSize,
- actualSize);
+ if (actualSize != bufSize) {
+ fprintf(stderr, "ReadEntityHeader expected dataSize %zu got %zu\n",
+ bufSize, actualSize);
err = EINVAL;
goto finished;
}
diff --git a/libs/androidfw/CursorWindow.cpp b/libs/androidfw/CursorWindow.cpp
index 2b74a33..166863c 100644
--- a/libs/androidfw/CursorWindow.cpp
+++ b/libs/androidfw/CursorWindow.cpp
@@ -210,8 +210,8 @@
uint32_t offset = mHeader->freeOffset + padding;
uint32_t nextFreeOffset = offset + size;
if (nextFreeOffset > mSize) {
- ALOGW("Window is full: requested allocation %d bytes, "
- "free space %d bytes, window size %d bytes",
+ ALOGW("Window is full: requested allocation %zu bytes, "
+ "free space %zu bytes, window size %zu bytes",
size, freeSpace(), mSize);
return 0;
}
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 652cd4a..7616ab0 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -42,6 +42,7 @@
#define TABLE_SUPER_NOISY(x) //x
#define LOAD_TABLE_NOISY(x) //x
#define TABLE_THEME(x) //x
+#define LIB_NOISY(x) x
namespace android {
@@ -66,6 +67,9 @@
// size measured in sizeof(uint32_t)
#define IDMAP_HEADER_SIZE (ResTable::IDMAP_HEADER_SIZE_BYTES / sizeof(uint32_t))
+#define APP_PACKAGE_ID 0x7f
+#define SYS_PACKAGE_ID 0x01
+
// Standard C isspace() is only required to look at the low byte of its input, so
// produces incorrect results for UTF-16 characters. For safety's sake, assume that
// any high-byte UTF-16 code point is not whitespace.
@@ -113,7 +117,7 @@
name, size, headerSize);
return BAD_TYPE;
}
- ALOGW("%s header size 0x%x is too small.",
+ ALOGW("%s header size 0x%04x is too small.",
name, headerSize);
return BAD_TYPE;
}
@@ -264,7 +268,7 @@
}
const uint32_t index = typeOffset + 2 + entry - entryOffset;
if (index > size) {
- ALOGW("Resource ID map: entry index=%d exceeds size of map=%d\n", index, (int)size);
+ ALOGW("Resource ID map: entry index=%u exceeds size of map=%d\n", index, (int)size);
*outValue = 0;
return NO_ERROR;
}
@@ -279,7 +283,7 @@
return UNKNOWN_ERROR;
}
if (mapSize <= IDMAP_HEADER_SIZE + 1) {
- ALOGW("corrupt idmap: map size %d too short\n", mapSize);
+ ALOGW("corrupt idmap: map size %d too short\n", (int)mapSize);
return UNKNOWN_ERROR;
}
uint32_t typeCount = *(map + IDMAP_HEADER_SIZE);
@@ -288,7 +292,7 @@
return UNKNOWN_ERROR;
}
if (IDMAP_HEADER_SIZE + 1 + typeCount > mapSize) {
- ALOGW("corrupt idmap: number of types %d extends past idmap size %d\n", typeCount, mapSize);
+ ALOGW("corrupt idmap: number of types %u extends past idmap size %d\n", typeCount, (int)mapSize);
return UNKNOWN_ERROR;
}
const uint32_t* p = map + IDMAP_HEADER_SIZE + 1;
@@ -304,7 +308,7 @@
// determine package id from first entry of first type
const uint32_t offset = *p + IDMAP_HEADER_SIZE + 2;
if (offset > mapSize) {
- ALOGW("corrupt idmap: entry offset %d points outside map size %d\n", offset, mapSize);
+ ALOGW("corrupt idmap: entry offset %u points outside map size %d\n", offset, (int)mapSize);
return UNKNOWN_ERROR;
}
*outId = (map[offset] >> 24) & 0x000000ff;
@@ -342,6 +346,22 @@
uninit();
}
+void ResStringPool::setToEmpty()
+{
+ uninit();
+
+ mOwnedData = calloc(1, sizeof(ResStringPool_header));
+ ResStringPool_header* header = (ResStringPool_header*) mOwnedData;
+ mSize = 0;
+ mEntries = NULL;
+ mStrings = NULL;
+ mStringPoolSize = 0;
+ mEntryStyles = NULL;
+ mStyles = NULL;
+ mStylePoolSize = 0;
+ mHeader = (const ResStringPool_header*) header;
+}
+
status_t ResStringPool::setTo(const void* data, size_t size, bool copyData)
{
if (!data || !size) {
@@ -1111,7 +1131,14 @@
(((const uint8_t*)tag)
+ dtohs(tag->attributeStart)
+ (dtohs(tag->attributeSize)*idx));
- return attr->typedValue.dataType;
+ uint8_t type = attr->typedValue.dataType;
+ if (type != Res_value::TYPE_DYNAMIC_REFERENCE) {
+ return type;
+ }
+
+ // This is a dynamic reference. We adjust those references
+ // to regular references at this level, so lie to the caller.
+ return Res_value::TYPE_REFERENCE;
}
}
return Res_value::TYPE_NULL;
@@ -1126,7 +1153,15 @@
(((const uint8_t*)tag)
+ dtohs(tag->attributeStart)
+ (dtohs(tag->attributeSize)*idx));
- return dtohl(attr->typedValue.data);
+ if (attr->typedValue.dataType != Res_value::TYPE_DYNAMIC_REFERENCE ||
+ mTree.mDynamicRefTable == NULL) {
+ return dtohl(attr->typedValue.data);
+ }
+
+ uint32_t data = dtohl(attr->typedValue.data);
+ if (mTree.mDynamicRefTable->lookupResourceId(&data) == NO_ERROR) {
+ return data;
+ }
}
}
return 0;
@@ -1142,6 +1177,10 @@
+ dtohs(tag->attributeStart)
+ (dtohs(tag->attributeSize)*idx));
outValue->copyFrom_dtoh(attr->typedValue);
+ if (mTree.mDynamicRefTable != NULL &&
+ mTree.mDynamicRefTable->lookupResourceValue(outValue) != NO_ERROR) {
+ return BAD_TYPE;
+ }
return sizeof(Res_value);
}
}
@@ -1333,25 +1372,26 @@
mCurExt = pos.curExt;
}
-
// --------------------------------------------------------------------
static volatile int32_t gCount = 0;
-ResXMLTree::ResXMLTree()
+ResXMLTree::ResXMLTree(const DynamicRefTable* dynamicRefTable)
: ResXMLParser(*this)
+ , mDynamicRefTable(dynamicRefTable)
, mError(NO_INIT), mOwnedData(NULL)
{
//ALOGI("Creating ResXMLTree %p #%d\n", this, android_atomic_inc(&gCount)+1);
restart();
}
-ResXMLTree::ResXMLTree(const void* data, size_t size, bool copyData)
+ResXMLTree::ResXMLTree()
: ResXMLParser(*this)
+ , mDynamicRefTable(NULL)
, mError(NO_INIT), mOwnedData(NULL)
{
//ALOGI("Creating ResXMLTree %p #%d\n", this, android_atomic_inc(&gCount)+1);
- setTo(data, size, copyData);
+ restart();
}
ResXMLTree::~ResXMLTree()
@@ -2737,7 +2777,14 @@
struct ResTable::PackageGroup
{
PackageGroup(ResTable* _owner, const String16& _name, uint32_t _id)
- : owner(_owner), name(_name), id(_id), typeCount(0), bags(NULL) { }
+ : owner(_owner)
+ , name(_name)
+ , id(_id)
+ , typeCount(0)
+ , bags(NULL)
+ , dynamicRefTable(static_cast<uint8_t>(_id))
+ { }
+
~PackageGroup() {
clearBagCache();
const size_t N = packages.size();
@@ -2790,6 +2837,13 @@
// Computed attribute bags, first indexed by the type and second
// by the entry in that type.
bag_set*** bags;
+
+ // The table mapping dynamic references to resolved references for
+ // this package group.
+ // TODO: We may be able to support dynamic references in overlays
+ // by having these tables in a per-package scope rather than
+ // per-package-group.
+ DynamicRefTable dynamicRefTable;
};
struct ResTable::bag_set
@@ -3077,7 +3131,7 @@
}
ResTable::ResTable()
- : mError(NO_INIT)
+ : mError(NO_INIT), mNextPackageId(2)
{
memset(&mParams, 0, sizeof(mParams));
memset(mPackageMap, 0, sizeof(mPackageMap));
@@ -3085,11 +3139,11 @@
}
ResTable::ResTable(const void* data, size_t size, const int32_t cookie, bool copyData)
- : mError(NO_INIT)
+ : mError(NO_INIT), mNextPackageId(2)
{
memset(&mParams, 0, sizeof(mParams));
memset(mPackageMap, 0, sizeof(mPackageMap));
- addInternal(data, size, cookie, NULL /* asset */, copyData, NULL /* idMap */);
+ addInternal(data, size, cookie, copyData, NULL /* idMap */);
LOG_FATAL_IF(mError != NO_ERROR, "Error parsing resource table");
//ALOGI("Creating ResTable %p\n", this);
}
@@ -3106,7 +3160,7 @@
}
status_t ResTable::add(const void* data, size_t size) {
- return addInternal(data, size, 0 /* cookie */, NULL /* asset */,
+ return addInternal(data, size, 0 /* cookie */,
false /* copyData */, NULL /* idMap */);
}
@@ -3118,7 +3172,7 @@
return UNKNOWN_ERROR;
}
size_t size = (size_t)asset->getLength();
- return addInternal(data, size, cookie, asset, copyData,
+ return addInternal(data, size, cookie, copyData,
reinterpret_cast<const Asset*>(idmap));
}
@@ -3146,8 +3200,25 @@
return mError;
}
+status_t ResTable::addEmpty(const int32_t cookie) {
+ Header* header = new Header(this);
+ header->index = mHeaders.size();
+ header->cookie = cookie;
+ header->values.setToEmpty();
+ header->ownedData = calloc(1, sizeof(ResTable_header));
+
+ ResTable_header* resHeader = (ResTable_header*) header->ownedData;
+ resHeader->header.type = RES_TABLE_TYPE;
+ resHeader->header.headerSize = sizeof(ResTable_header);
+ resHeader->header.size = sizeof(ResTable_header);
+
+ header->header = (const ResTable_header*) resHeader;
+ mHeaders.add(header);
+ return NO_ERROR;
+}
+
status_t ResTable::addInternal(const void* data, size_t size, const int32_t cookie,
- Asset* /*asset*/, bool copyData, const Asset* idmap)
+ bool copyData, const Asset* idmap)
{
if (!data) return NO_ERROR;
Header* header = new Header(this);
@@ -3186,8 +3257,6 @@
//ALOGI("Got size 0x%x, again size 0x%x, raw size 0x%x\n", header->size,
// dtohl(header->header->header.size), header->header->header.size);
LOAD_TABLE_NOISY(ALOGV("Loading ResTable @%p:\n", header->header));
- LOAD_TABLE_NOISY(printHexData(2, header->header, header->size < 256 ? header->size : 256,
- 16, 16, 0, false, printToLogFunc));
if (dtohs(header->header->header.headerSize) > header->size
|| header->size > size) {
ALOGW("Bad resource table: header size 0x%x or total size 0x%x is larger than data size 0x%x\n",
@@ -3474,9 +3543,6 @@
continue;
}
- TABLE_NOISY(aout << "Resource type data: "
- << HexDump(type, dtohl(type->header.size)) << endl);
-
if ((size_t)offset > (dtohl(type->header.size)-sizeof(Res_value))) {
ALOGW("ResTable_item at %d is beyond type chunk data %d",
(int)offset, dtohl(type->header.size));
@@ -3516,6 +3582,18 @@
outValue->res0 = bestValue->res0;
outValue->dataType = bestValue->dataType;
outValue->data = dtohl(bestValue->data);
+
+ // The reference may be pointing to a resource in a shared library. These
+ // references have build-time generated package IDs. These ids may not match
+ // the actual package IDs of the corresponding packages in this ResTable.
+ // We need to fix the package ID based on a mapping.
+ status_t err = grp->dynamicRefTable.lookupResourceValue(outValue);
+ if (err != NO_ERROR) {
+ ALOGW("Failed to resolve referenced package: 0x%08x", outValue->data);
+ rc = BAD_VALUE;
+ goto out;
+ }
+
if (outConfig != NULL) {
*outConfig = bestItem;
}
@@ -3545,8 +3623,8 @@
ResTable_config* outConfig) const
{
int count=0;
- while (blockIndex >= 0 && value->dataType == value->TYPE_REFERENCE
- && value->data != 0 && count < 20) {
+ while (blockIndex >= 0 && value->dataType == Res_value::TYPE_REFERENCE
+ && value->data != 0 && count < 20) {
if (outLastRef) *outLastRef = value->data;
uint32_t lastRef = value->data;
uint32_t newFlags = 0;
@@ -3730,7 +3808,7 @@
const Type* typeClass;
ALOGV("Getting entry pkg=%p, t=%d, e=%d\n", package, T, E);
ssize_t offset = getEntry(package, T, E, &mParams, &type, &entry, &typeClass);
- ALOGV("Resulting offset=%d\n", offset);
+ ALOGV("Resulting offset=%d\n", (int)offset);
if (offset <= 0) {
// No {entry, appropriate config} pair found in package. If this
// package is an overlay package (ip != 0), this simply means the
@@ -3774,9 +3852,21 @@
TABLE_NOISY(printf("Creating new bag, entrySize=0x%08x, parent=0x%08x\n",
entrySize, parent));
if (parent) {
+ uint32_t resolvedParent = parent;
+
+ // Bags encode a parent reference without using the standard
+ // Res_value structure. That means we must always try to
+ // resolve a parent reference in case it is actually a
+ // TYPE_DYNAMIC_REFERENCE.
+ status_t err = grp->dynamicRefTable.lookupResourceId(&resolvedParent);
+ if (err != NO_ERROR) {
+ ALOGE("Failed resolving bag parent id 0x%08x", parent);
+ return UNKNOWN_ERROR;
+ }
+
const bag_entry* parentBag;
uint32_t parentTypeSpecFlags = 0;
- const ssize_t NP = getBagLocked(parent, &parentBag, &parentTypeSpecFlags);
+ const ssize_t NP = getBagLocked(resolvedParent, &parentBag, &parentTypeSpecFlags);
const size_t NT = ((NP >= 0) ? NP : 0) + N;
set = (bag_set*)malloc(sizeof(bag_set)+sizeof(bag_entry)*NT);
if (set == NULL) {
@@ -3871,6 +3961,12 @@
cur->stringBlock = package->header->index;
cur->map.name.ident = newName;
cur->map.value.copyFrom_dtoh(map->value);
+ status_t err = grp->dynamicRefTable.lookupResourceValue(&cur->map.value);
+ if (err != NO_ERROR) {
+ ALOGE("Reference item(0x%08x) in bag could not be resolved.", cur->map.value.data);
+ return UNKNOWN_ERROR;
+ }
+
TABLE_NOISY(printf("Setting entry #%d %p: block=%d, name=0x%08x, type=%d, data=0x%08x\n",
curEntry, cur, cur->stringBlock, cur->map.name.ident,
cur->map.value.dataType, cur->map.value.data));
@@ -4568,16 +4664,20 @@
return false;
}
}
- if (!accessor) {
- outValue->data = rid;
- return true;
+
+ if (accessor) {
+ rid = Res_MAKEID(
+ accessor->getRemappedPackage(Res_GETPACKAGE(rid)),
+ Res_GETTYPE(rid), Res_GETENTRY(rid));
+ TABLE_NOISY(printf("Incl %s:%s/%s: 0x%08x\n",
+ String8(package).string(), String8(type).string(),
+ String8(name).string(), rid));
}
- rid = Res_MAKEID(
- accessor->getRemappedPackage(Res_GETPACKAGE(rid)),
- Res_GETTYPE(rid), Res_GETENTRY(rid));
- TABLE_NOISY(printf("Incl %s:%s/%s: 0x%08x\n",
- String8(package).string(), String8(type).string(),
- String8(name).string(), rid));
+
+ uint32_t packageId = Res_GETPACKAGE(rid) + 1;
+ if (packageId != APP_PACKAGE_ID && packageId != SYS_PACKAGE_ID) {
+ outValue->dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
+ }
outValue->data = rid;
return true;
}
@@ -4589,8 +4689,17 @@
TABLE_NOISY(printf("Pckg %s:%s/%s: 0x%08x\n",
String8(package).string(), String8(type).string(),
String8(name).string(), rid));
- outValue->data = rid;
- return true;
+ uint32_t packageId = Res_GETPACKAGE(rid) + 1;
+ if (packageId == 0x00) {
+ outValue->data = rid;
+ outValue->dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
+ return true;
+ } else if (packageId == APP_PACKAGE_ID || packageId == SYS_PACKAGE_ID) {
+ // We accept packageId's generated as 0x01 in order to support
+ // building the android system resources
+ outValue->data = rid;
+ return true;
+ }
}
}
}
@@ -5122,15 +5231,15 @@
return mPackageGroups.size();
}
-const char16_t* ResTable::getBasePackageName(size_t idx) const
+const String16 ResTable::getBasePackageName(size_t idx) const
{
if (mError != NO_ERROR) {
- return 0;
+ return String16();
}
LOG_FATAL_IF(idx >= mPackageGroups.size(),
"Requested package index %d past package count %d",
(int)idx, (int)mPackageGroups.size());
- return mPackageGroups[idx]->name.string();
+ return mPackageGroups[idx]->name;
}
uint32_t ResTable::getBasePackageId(size_t idx) const
@@ -5159,6 +5268,21 @@
return mHeaders[index]->cookie;
}
+const DynamicRefTable* ResTable::getDynamicRefTableForCookie(int32_t cookie) const
+{
+ const size_t N = mPackageGroups.size();
+ for (size_t i = 0; i < N; i++) {
+ const PackageGroup* pg = mPackageGroups[i];
+ size_t M = pg->packages.size();
+ for (size_t j = 0; j < M; j++) {
+ if (pg->packages[j]->header->cookie == cookie) {
+ return &pg->dynamicRefTable;
+ }
+ }
+ }
+ return NULL;
+}
+
void ResTable::getConfigurations(Vector<ResTable_config>* configs) const
{
const size_t I = mPackageGroups.size();
@@ -5300,10 +5424,9 @@
}
offset += dtohl(type->entriesStart);
- TABLE_NOISY(aout << "Looking in resource table " << package->header->header
- << ", typeOff="
- << (void*)(((const char*)type)-((const char*)package->header->header))
- << ", offset=" << (void*)offset << endl);
+ TABLE_NOISY(ALOGD("Looking in resource table %p, typeOff=%p, offset=%p",
+ package->header->header, (void*)(((const char*)type)-((const char*)package->header->header)),
+ (void*)offset));
if (offset > (dtohl(type->header.size)-sizeof(ResTable_entry))) {
ALOGW("ResTable_entry at 0x%x is beyond type chunk data 0x%x",
@@ -5377,6 +5500,11 @@
if (package == NULL) {
return (mError=NO_MEMORY);
}
+
+ if (id == 0) {
+ // This is a library so assign an ID
+ id = mNextPackageId++;
+ }
size_t idx = mPackageMap[id];
if (idx == 0) {
@@ -5413,6 +5541,13 @@
group->basePackage = package;
mPackageMap[id] = (uint8_t)idx;
+
+ // Find all packages that reference this package
+ size_t N = mPackageGroups.size();
+ for (size_t i = 0; i < N; i++) {
+ mPackageGroups[i]->dynamicRefTable.addMapping(
+ group->name, static_cast<uint8_t>(group->id));
+ }
} else {
group = mPackageGroups.itemAt(idx-1);
if (group == NULL) {
@@ -5457,7 +5592,7 @@
(void*)(base-(const uint8_t*)chunk),
dtohs(typeSpec->header.type),
dtohs(typeSpec->header.headerSize),
- (void*)typeSize));
+ (void*)typeSpecSize));
// look for block overrun or int overflow when multiplying by 4
if ((dtohl(typeSpec->entryCount) > (INT32_MAX/sizeof(uint32_t))
|| dtohs(typeSpec->header.headerSize)+(sizeof(uint32_t)*dtohl(typeSpec->entryCount))
@@ -5543,6 +5678,21 @@
ALOGI("Adding config to type %d: %s\n",
type->id, thisConfig.toString().string()));
t->configs.add(type);
+ } else if (ctype == RES_TABLE_LIBRARY_TYPE) {
+ if (group->dynamicRefTable.entries().size() == 0) {
+ status_t err = group->dynamicRefTable.load((const ResTable_lib_header*) chunk);
+ if (err != NO_ERROR) {
+ return (mError=err);
+ }
+
+ // Fill in the reference table with the entries we already know about.
+ size_t N = mPackageGroups.size();
+ for (size_t i = 0; i < N; i++) {
+ group->dynamicRefTable.addMapping(mPackageGroups[i]->name, mPackageGroups[i]->id);
+ }
+ } else {
+ ALOGW("Found multiple library tables, ignoring...");
+ }
} else {
status_t err = validate_chunk(chunk, sizeof(ResChunk_header),
endPos, "ResTable_package:unknown");
@@ -5561,6 +5711,103 @@
return NO_ERROR;
}
+DynamicRefTable::DynamicRefTable(uint8_t packageId)
+ : mAssignedPackageId(packageId)
+{
+ memset(mLookupTable, 0, sizeof(mLookupTable));
+
+ // Reserved package ids
+ mLookupTable[APP_PACKAGE_ID] = APP_PACKAGE_ID;
+ mLookupTable[SYS_PACKAGE_ID] = SYS_PACKAGE_ID;
+}
+
+status_t DynamicRefTable::load(const ResTable_lib_header* const header)
+{
+ const uint32_t entryCount = dtohl(header->count);
+ const uint32_t sizeOfEntries = sizeof(ResTable_lib_entry) * entryCount;
+ const uint32_t expectedSize = dtohl(header->header.size) - dtohl(header->header.headerSize);
+ if (sizeOfEntries > expectedSize) {
+ ALOGE("ResTable_lib_header size %u is too small to fit %u entries (x %u).",
+ expectedSize, entryCount, (uint32_t)sizeof(ResTable_lib_entry));
+ return UNKNOWN_ERROR;
+ }
+
+ const ResTable_lib_entry* entry = (const ResTable_lib_entry*)(((uint8_t*) header) +
+ dtohl(header->header.headerSize));
+ for (uint32_t entryIndex = 0; entryIndex < entryCount; entryIndex++) {
+ uint32_t packageId = dtohl(entry->packageId);
+ char16_t tmpName[sizeof(entry->packageName) / sizeof(char16_t)];
+ strcpy16_dtoh(tmpName, entry->packageName, sizeof(entry->packageName) / sizeof(char16_t));
+ LIB_NOISY(ALOGV("Found lib entry %s with id %d\n", String8(tmpName).string(),
+ dtohl(entry->packageId)));
+ if (packageId >= 256) {
+ ALOGE("Bad package id 0x%08x", packageId);
+ return UNKNOWN_ERROR;
+ }
+ mEntries.replaceValueFor(String16(tmpName), (uint8_t) packageId);
+ entry = entry + 1;
+ }
+ return NO_ERROR;
+}
+
+status_t DynamicRefTable::addMapping(const String16& packageName, uint8_t packageId)
+{
+ ssize_t index = mEntries.indexOfKey(packageName);
+ if (index < 0) {
+ return UNKNOWN_ERROR;
+ }
+ mLookupTable[mEntries.valueAt(index)] = packageId;
+ return NO_ERROR;
+}
+
+status_t DynamicRefTable::lookupResourceId(uint32_t* resId) const {
+ uint32_t res = *resId;
+ size_t packageId = Res_GETPACKAGE(res) + 1;
+
+ if (packageId == APP_PACKAGE_ID) {
+ // No lookup needs to be done, app package IDs are absolute.
+ return NO_ERROR;
+ }
+
+ if (packageId == 0) {
+ // The package ID is 0x00. That means that a shared library is accessing
+ // its own local resource, so we fix up the resource with the calling
+ // package ID.
+ *resId |= ((uint32_t) mAssignedPackageId) << 24;
+ return NO_ERROR;
+ }
+
+ // Do a proper lookup.
+ uint8_t translatedId = mLookupTable[packageId];
+ if (translatedId == 0) {
+ ALOGV("DynamicRefTable(0x%02x): No mapping for build-time package ID 0x%02x.",
+ (uint8_t)mAssignedPackageId, (uint8_t)packageId);
+ for (size_t i = 0; i < 256; i++) {
+ if (mLookupTable[i] != 0) {
+ ALOGV("e[0x%02x] -> 0x%02x", (uint8_t)i, mLookupTable[i]);
+ }
+ }
+ return UNKNOWN_ERROR;
+ }
+
+ *resId = (res & 0x00ffffff) | (((uint32_t) translatedId) << 24);
+ return NO_ERROR;
+}
+
+status_t DynamicRefTable::lookupResourceValue(Res_value* value) const {
+ if (value->dataType != Res_value::TYPE_DYNAMIC_REFERENCE) {
+ return NO_ERROR;
+ }
+
+ status_t err = lookupResourceId(&value->data);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ value->dataType = Res_value::TYPE_REFERENCE;
+ return NO_ERROR;
+}
+
status_t ResTable::createIdmap(const ResTable& overlay,
uint32_t targetCrc, uint32_t overlayCrc,
const char* targetPath, const char* overlayPath,
@@ -5701,7 +5948,7 @@
continue;
}
if (N == 1) { // vector expected to hold (offset) + (N > 0 entries)
- ALOGW("idmap: type %d supposedly has entries, but no entries found\n", i);
+ ALOGW("idmap: type %u supposedly has entries, but no entries found\n", (uint32_t)i);
return UNKNOWN_ERROR;
}
*data++ = htodl(N - 1); // do not count the offset (which is vector's first element)
@@ -5815,6 +6062,8 @@
printf("(null)\n");
} else if (value.dataType == Res_value::TYPE_REFERENCE) {
printf("(reference) 0x%08x\n", value.data);
+ } else if (value.dataType == Res_value::TYPE_DYNAMIC_REFERENCE) {
+ printf("(dynamic reference) 0x%08x\n", value.data);
} else if (value.dataType == Res_value::TYPE_ATTRIBUTE) {
printf("(attribute) 0x%08x\n", value.data);
} else if (value.dataType == Res_value::TYPE_STRING) {
@@ -5897,6 +6146,11 @@
uint32_t resID = (0xff000000 & ((pkg->package->id)<<24))
| (0x00ff0000 & ((typeIndex+1)<<16))
| (0x0000ffff & (entryIndex));
+ // Since we are creating resID without actually
+ // iterating over them, we have no idea which is a
+ // dynamic reference. We must check.
+ pg->dynamicRefTable.lookupResourceId(&resID);
+
resource_name resName;
if (this->getResourceName(resID, true, &resName)) {
String8 type8;
@@ -5956,6 +6210,7 @@
uint32_t resID = (0xff000000 & ((pkg->package->id)<<24))
| (0x00ff0000 & ((typeIndex+1)<<16))
| (0x0000ffff & (entryIndex));
+ pg->dynamicRefTable.lookupResourceId(&resID);
resource_name resName;
if (this->getResourceName(resID, true, &resName)) {
String8 type8;
@@ -5996,12 +6251,12 @@
uintptr_t esize = dtohs(ent->size);
if ((esize&0x3) != 0) {
- printf("NON-INTEGER ResTable_entry SIZE: 0x%x\n", esize);
+ printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void *)esize);
continue;
}
if ((thisOffset+esize) > typeSize) {
- printf("ResTable_entry OUT OF BOUNDS: 0x%x+0x%x+0x%x (size is 0x%x)\n",
- entriesStart, thisOffset, esize, typeSize);
+ printf("ResTable_entry OUT OF BOUNDS: 0x%x+0x%x+%p (size is 0x%x)\n",
+ entriesStart, thisOffset, (void *)esize, typeSize);
continue;
}
@@ -6034,8 +6289,14 @@
const uint8_t* baseMapPtr = (const uint8_t*)ent;
size_t mapOffset = esize;
const ResTable_map* mapPtr = (ResTable_map*)(baseMapPtr+mapOffset);
- printf(" Parent=0x%08x, Count=%d\n",
- dtohl(bagPtr->parent.ident), N);
+ const uint32_t parent = dtohl(bagPtr->parent.ident);
+ uint32_t resolvedParent = parent;
+ status_t err = pg->dynamicRefTable.lookupResourceId(&resolvedParent);
+ if (err != NO_ERROR) {
+ resolvedParent = 0;
+ }
+ printf(" Parent=0x%08x(Resolved=0x%08x), Count=%d\n",
+ parent, resolvedParent, N);
for (int i=0; i<N && mapOffset < (typeSize-sizeof(ResTable_map)); i++) {
printf(" #%i (Key=0x%08x): ",
i, dtohl(mapPtr->name.ident));
diff --git a/libs/androidfw/tests/ObbFile_test.cpp b/libs/androidfw/tests/ObbFile_test.cpp
index 2c9f650..7a4dd13 100644
--- a/libs/androidfw/tests/ObbFile_test.cpp
+++ b/libs/androidfw/tests/ObbFile_test.cpp
@@ -91,7 +91,7 @@
EXPECT_EQ(sizeof(salt), saltLen)
<< "salt sizes were not the same";
- for (int i = 0; i < sizeof(salt); i++) {
+ for (size_t i = 0; i < sizeof(salt); i++) {
EXPECT_EQ(salt[i], newSalt[i])
<< "salt character " << i << " should be equal";
}
diff --git a/libs/common_time/common_time_server.cpp b/libs/common_time/common_time_server.cpp
index 21e706f..3e11987 100644
--- a/libs/common_time/common_time_server.cpp
+++ b/libs/common_time/common_time_server.cpp
@@ -590,7 +590,7 @@
for (i = 0; (i < src_len) && (offset < dst_len); ++i) {
int res;
if (0 == (i % 16)) {
- res = snprintf(dst + offset, dst_len - offset, "\n%04x :", i);
+ res = snprintf(dst + offset, dst_len - offset, "\n%04zx :", i);
if (res < 0)
break;
offset += res;
diff --git a/libs/common_time/utils.cpp b/libs/common_time/utils.cpp
index ed2c77d..ddcdfe7 100644
--- a/libs/common_time/utils.cpp
+++ b/libs/common_time/utils.cpp
@@ -56,7 +56,7 @@
, mHeader(header) {
mRingBuffer = new Entry[mSize];
if (NULL == mRingBuffer)
- ALOGE("Failed to allocate log ring with %u entries.", mSize);
+ ALOGE("Failed to allocate log ring with %zu entries.", mSize);
}
LogRing::~LogRing() {
@@ -150,7 +150,7 @@
localtime_r(&mRingBuffer[ndx].first_ts.tv_sec, &t);
strftime(timebuf, sizeof(timebuf), kTimeFmt, &t);
- res = snprintf(buf, sizeof(buf), "[%2d] %s.%03ld :: %s%s\n",
+ res = snprintf(buf, sizeof(buf), "[%2zu] %s.%03ld :: %s%s\n",
i, timebuf,
mRingBuffer[ndx].first_ts.tv_usec / 1000,
mRingBuffer[ndx].s.string(),
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 4de755d..52be531 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -54,6 +54,7 @@
# RenderThread stuff
LOCAL_SRC_FILES += \
renderthread/CanvasContext.cpp \
+ renderthread/DrawFrameTask.cpp \
renderthread/RenderProxy.cpp \
renderthread/RenderTask.cpp \
renderthread/RenderThread.cpp
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 7380bbf..5b4e03f 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -29,7 +29,6 @@
, mNeedsGLContextAttach(false)
, mUpdateTexImage(false)
, mLayer(layer)
- , mRenderer(renderer)
, mCaches(Caches::getInstance()) {
mWidth = mLayer->layer.getWidth();
mHeight = mLayer->layer.getHeight();
@@ -45,7 +44,6 @@
if (mLayer) {
mCaches.resourceCache.decrementRefcount(mLayer);
}
- delete mRenderer;
}
void DeferredLayerUpdater::setPaint(const SkPaint* paint) {
@@ -76,7 +74,7 @@
}
mLayer->setBlend(mBlend);
mDisplayList->updateProperties();
- mLayer->updateDeferred(mRenderer, mDisplayList,
+ mLayer->updateDeferred(mDisplayList,
mDirtyRect.left, mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom);
mDirtyRect.setEmpty();
mDisplayList = 0;
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index cf745ee..10fa264 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -109,7 +109,6 @@
bool mUpdateTexImage;
Layer* mLayer;
- OpenGLRenderer* mRenderer;
Caches& mCaches;
void doUpdateTexImage();
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 549b786..5fa8f1d 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -21,6 +21,8 @@
#define LOG_TAG "OpenGLRenderer"
#endif
+#include <SkPath.h>
+#include <SkPathOps.h>
#include <SkXfermode.h>
#include <private/hwui/DrawGlInfo.h>
@@ -1497,13 +1499,13 @@
virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
bool useQuickReject) {
if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
- mDisplayList->defer(deferStruct, level + 1);
+ mDisplayList->deferNodeInParent(deferStruct, level + 1);
}
}
virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
bool useQuickReject) {
if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
- mDisplayList->replay(replayStruct, level + 1);
+ mDisplayList->replayNodeInParent(replayStruct, level + 1);
}
}
@@ -1546,24 +1548,34 @@
};
/**
- * Not a canvas operation, used only by 3d / z ordering logic in DisplayList::iterate()
+ * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate()
*/
class DrawShadowOp : public DrawOp {
public:
- DrawShadowOp(const mat4& transformXY, const mat4& transformZ, float alpha, const SkPath* outline,
- float fallbackWidth, float fallbackHeight)
+ DrawShadowOp(const mat4& transformXY, const mat4& transformZ,
+ float casterAlpha, bool casterUnclipped,
+ float fallbackWidth, float fallbackHeight,
+ const SkPath* outline, const SkPath* revealClip)
: DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ),
- mAlpha(alpha), mOutline(outline),
- mFallbackWidth(fallbackWidth), mFallbackHeight(fallbackHeight) {}
+ mCasterAlpha(casterAlpha), mCasterUnclipped(casterUnclipped),
+ mFallbackWidth(fallbackWidth), mFallbackHeight(fallbackHeight),
+ mOutline(outline), mRevealClip(revealClip) {}
virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
- if (mOutline->isEmpty()) {
- SkPath fakeOutline;
- fakeOutline.addRect(0, 0, mFallbackWidth, mFallbackHeight);
- return renderer.drawShadow(mTransformXY, mTransformZ, mAlpha, &fakeOutline);
+ SkPath casterPerimeter;
+ if (!mOutline || mOutline->isEmpty()) {
+ casterPerimeter.addRect(0, 0, mFallbackWidth, mFallbackHeight);
+ } else {
+ casterPerimeter = *mOutline;
}
- return renderer.drawShadow(mTransformXY, mTransformZ, mAlpha, mOutline);
+ if (mRevealClip) {
+ // intersect the outline with the convex reveal clip
+ Op(casterPerimeter, *mRevealClip, kIntersect_PathOp, &casterPerimeter);
+ }
+
+ return renderer.drawShadow(mTransformXY, mTransformZ,
+ mCasterAlpha, mCasterUnclipped, &casterPerimeter);
}
virtual void output(int level, uint32_t logFlags) const {
@@ -1575,10 +1587,14 @@
private:
const mat4 mTransformXY;
const mat4 mTransformZ;
- const float mAlpha;
- const SkPath* mOutline;
+ const float mCasterAlpha;
+ const bool mCasterUnclipped;
const float mFallbackWidth;
const float mFallbackHeight;
+
+ // these point at convex SkPaths owned by RenderProperties, or null
+ const SkPath* mOutline;
+ const SkPath* mRevealClip;
};
class DrawLayerOp : public DrawOp {
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index bd9bfe9..27409a2 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -58,6 +58,7 @@
delete[] mesh;
delete deferredList;
+ delete renderer;
}
uint32_t Layer::computeIdealWidth(uint32_t layerWidth) {
@@ -68,6 +69,13 @@
return uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE);
}
+void Layer::requireRenderer() {
+ if (!renderer) {
+ renderer = new LayerRenderer(this);
+ renderer->initProperties();
+ }
+}
+
bool Layer::resize(const uint32_t width, const uint32_t height) {
uint32_t desiredWidth = computeIdealWidth(width);
uint32_t desiredHeight = computeIdealWidth(height);
@@ -201,13 +209,12 @@
dirtyRect.right, dirtyRect.bottom, !isBlend());
displayList->computeOrdering();
- displayList->defer(deferredState, 0);
+ displayList->deferNodeTree(deferredState);
deferredUpdateScheduled = false;
}
void Layer::cancelDefer() {
- renderer = NULL;
displayList = NULL;
deferredUpdateScheduled = false;
if (deferredList) {
@@ -226,7 +233,6 @@
deferredList->flush(*renderer, dirtyRect);
renderer->finish();
- renderer = NULL;
dirtyRect.setEmpty();
displayList = NULL;
@@ -241,7 +247,6 @@
renderer->drawDisplayList(displayList, dirtyRect, RenderNode::kReplayFlag_ClipChildren);
renderer->finish();
- renderer = NULL;
dirtyRect.setEmpty();
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index d8440ea..b428404 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -84,9 +84,9 @@
regionRect.translate(layer.left, layer.top);
}
- void updateDeferred(OpenGLRenderer* renderer, RenderNode* displayList,
+ void updateDeferred(RenderNode* displayList,
int left, int top, int right, int bottom) {
- this->renderer = renderer;
+ requireRenderer();
this->displayList = displayList;
const Rect r(left, top, right, bottom);
dirtyRect.unionWith(r);
@@ -300,6 +300,8 @@
bool hasDrawnSinceUpdate;
private:
+ void requireRenderer();
+
Caches& caches;
/**
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index cdd789d..e1f484d 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -409,15 +409,6 @@
for (size_t i = 0; i < count; i++) {
Functor* f = functors.itemAt(i);
result |= (*f)(DrawGlInfo::kModeProcess, &info);
-
- if (result & DrawGlInfo::kStatusDraw) {
- Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom);
- dirty.unionWith(localDirty);
- }
-
- if (result & DrawGlInfo::kStatusInvoke) {
- mFunctors.add(f);
- }
}
resume();
}
@@ -461,19 +452,10 @@
interrupt();
// call functor immediately after GL state setup
- status_t result = (*functor)(DrawGlInfo::kModeDraw, &info);
-
- if (result != DrawGlInfo::kStatusDone) {
- Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom);
- dirty.unionWith(localDirty);
-
- if (result & DrawGlInfo::kStatusInvoke) {
- mFunctors.add(functor);
- }
- }
+ (*functor)(DrawGlInfo::kModeDraw, &info);
resume();
- return result | DrawGlInfo::kStatusDrew;
+ return DrawGlInfo::kStatusDrew;
}
///////////////////////////////////////////////////////////////////////////////
@@ -1919,18 +1901,19 @@
// will be performed by the display list itself
if (displayList && displayList->isRenderable()) {
// compute 3d ordering
+ displayList->updateProperties();
displayList->computeOrdering();
if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
status = startFrame();
ReplayStateStruct replayStruct(*this, dirty, replayFlags);
- displayList->replay(replayStruct, 0);
+ displayList->replayNodeTree(replayStruct);
return status | replayStruct.mDrawGlStatus;
}
bool avoidOverdraw = !mCaches.debugOverdraw && !mCountOverdraw; // shh, don't tell devs!
DeferredDisplayList deferredList(*currentClipRect(), avoidOverdraw);
DeferStateStruct deferStruct(deferredList, *this, replayFlags);
- displayList->defer(deferStruct, 0);
+ displayList->deferNodeTree(deferStruct);
flushLayers();
status = startFrame();
@@ -3202,7 +3185,7 @@
}
status_t OpenGLRenderer::drawShadow(const mat4& casterTransformXY, const mat4& casterTransformZ,
- float casterAlpha, const SkPath* casterOutline) {
+ float casterAlpha, bool casterUnclipped, const SkPath* casterPerimeter) {
if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;
// TODO: use quickRejectWithScissor. For now, always force enable scissor.
@@ -3214,7 +3197,7 @@
// tessellate caster outline into a 2d polygon
Vector<Vertex> casterVertices2d;
const float casterRefinementThresholdSquared = 20.0f; // TODO: experiment with this value
- PathTessellator::approximatePathOutlineVertices(*casterOutline,
+ PathTessellator::approximatePathOutlineVertices(*casterPerimeter,
casterRefinementThresholdSquared, casterVertices2d);
if (casterVertices2d.size() == 0) {
@@ -3256,10 +3239,10 @@
// We only have ortho projection, so we can just ignore the Z in caster for
// simple rejection calculation.
Rect localClip = mSnapshot->getLocalClip();
- Rect casterBounds(casterOutline->getBounds());
+ Rect casterBounds(casterPerimeter->getBounds());
casterTransformXY.mapRect(casterBounds);
- bool isCasterOpaque = (casterAlpha == 1.0f);
+ bool isCasterOpaque = (casterAlpha == 1.0f) && casterUnclipped;
// draw caster's shadows
if (mCaches.propertyAmbientShadowStrength > 0) {
paint.setARGB(casterAlpha * mCaches.propertyAmbientShadowStrength, 0, 0, 0);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 059c64f..2debd2e 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -210,7 +210,7 @@
virtual status_t drawRects(const float* rects, int count, const SkPaint* paint);
status_t drawShadow(const mat4& casterTransformXY, const mat4& casterTransformZ,
- float casterAlpha, const SkPath* casterOutline);
+ float casterAlpha, bool casterUnclipped, const SkPath* casterPerimeter);
virtual void resetShader();
virtual void setupShader(SkiaShader* shader);
diff --git a/libs/hwui/Outline.h b/libs/hwui/Outline.h
index 4e496e7..530be30 100644
--- a/libs/hwui/Outline.h
+++ b/libs/hwui/Outline.h
@@ -58,7 +58,6 @@
mShouldClip = clip;
}
-
bool willClip() const {
// only round rect outlines can be used for clipping
return mShouldClip && (mType == kOutlineType_RoundRect);
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index b2148b0..442e9ba 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -36,6 +36,7 @@
}
Patch::~Patch() {
+ delete[] vertices;
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index 8a44604..2f2debc 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -119,6 +119,17 @@
void PatchCache::removeDeferred(Res_png_9patch* patch) {
Mutex::Autolock _l(mLock);
+
+ // Assert that patch is not already garbage
+ size_t count = mGarbage.size();
+ for (size_t i = 0; i < count; i++) {
+ if (patch == mGarbage[i]) {
+ patch = NULL;
+ break;
+ }
+ }
+ LOG_ALWAYS_FATAL_IF(patch == NULL);
+
mGarbage.push(patch);
}
@@ -143,8 +154,8 @@
for (size_t i = 0; i < patchesToRemove.size(); i++) {
const patch_pair_t& pair = patchesToRemove[i];
- // Add a new free block to the list
- const Patch* patch = pair.getSecond();
+ // Release the patch and mark the space in the free list
+ Patch* patch = pair.getSecond();
BufferBlock* block = new BufferBlock(patch->offset, patch->getSize());
block->next = mFreeBlocks;
mFreeBlocks = block;
@@ -152,6 +163,7 @@
mSize -= patch->getSize();
mCache.remove(*pair.getFirst());
+ delete patch;
}
#if DEBUG_PATCHES
@@ -216,6 +228,7 @@
} else {
mFreeBlocks = block->next;
}
+ delete block;
} else {
// Resize the block now that it's occupied
block->offset += size;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index d3daec8..663b67e 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -61,8 +61,12 @@
void RenderNode::destroyDisplayListDeferred(RenderNode* displayList) {
if (displayList) {
- DISPLAY_LIST_LOGD("Deferring display list destruction");
- Caches::getInstance().deleteDisplayListDeferred(displayList);
+ if (Caches::hasInstance()) {
+ DISPLAY_LIST_LOGD("Deferring display list destruction");
+ Caches::getInstance().deleteDisplayListDeferred(displayList);
+ } else {
+ delete displayList;
+ }
}
}
@@ -107,6 +111,23 @@
}
}
+bool RenderNode::hasFunctors() {
+ if (!mDisplayListData) return false;
+
+ if (mDisplayListData->functorCount) {
+ return true;
+ }
+
+ for (size_t i = 0; i < mDisplayListData->children.size(); i++) {
+ RenderNode* childNode = mDisplayListData->children[i]->mDisplayList;
+ if (childNode->hasFunctors()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
/*
* For property operations, we pass a savecount of 0, since the operations aren't part of the
* displaylist, and thus don't have to compensate for the record-time/playback-time discrepancy in
@@ -115,10 +136,9 @@
#define PROPERTY_SAVECOUNT 0
template <class T>
-void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler,
- const int level) {
+void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler) {
#if DEBUG_DISPLAY_LIST
- properties().debugOutputProperties(level);
+ properties().debugOutputProperties(handler.level() + 1);
#endif
if (properties().getLeft() != 0 || properties().getTop() != 0) {
renderer.translate(properties().getLeft(), properties().getTop());
@@ -152,18 +172,21 @@
}
SaveLayerOp* op = new (handler.allocator()) SaveLayerOp(
- 0, 0, properties().getWidth(), properties().getHeight(), properties().getAlpha() * 255, saveFlags);
+ 0, 0, properties().getWidth(), properties().getHeight(),
+ properties().getAlpha() * 255, saveFlags);
handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
}
if (clipToBoundsNeeded) {
- ClipRectOp* op = new (handler.allocator()) ClipRectOp(0, 0,
- properties().getWidth(), properties().getHeight(), SkRegion::kIntersect_Op);
+ ClipRectOp* op = new (handler.allocator()) ClipRectOp(
+ 0, 0, properties().getWidth(), properties().getHeight(), SkRegion::kIntersect_Op);
handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
- if (CC_UNLIKELY(properties().getOutline().willClip())) {
- ClipPathOp* op = new (handler.allocator()) ClipPathOp(properties().getOutline().getPath(),
- SkRegion::kIntersect_Op);
+
+ if (CC_UNLIKELY(properties().hasClippingPath())) {
+ // TODO: optimize for round rect/circle clipping
+ const SkPath* path = properties().getClippingPath();
+ ClipPathOp* op = new (handler.allocator()) ClipPathOp(path, SkRegion::kIntersect_Op);
handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
}
@@ -282,7 +305,6 @@
child->computeOrderingImpl(childOp, projectionChildren, projectionTransform);
}
}
-
}
class DeferOperationHandler {
@@ -293,15 +315,25 @@
operation->defer(mDeferStruct, saveCount, mLevel, clipToBounds);
}
inline LinearAllocator& allocator() { return *(mDeferStruct.mAllocator); }
+ inline void startMark(const char* name) {} // do nothing
+ inline void endMark() {}
+ inline int level() { return mLevel; }
+ inline int replayFlags() { return mDeferStruct.mReplayFlags; }
private:
DeferStateStruct& mDeferStruct;
const int mLevel;
};
-void RenderNode::defer(DeferStateStruct& deferStruct, const int level) {
+void RenderNode::deferNodeTree(DeferStateStruct& deferStruct) {
+ DeferOperationHandler handler(deferStruct, 0);
+ if (properties().getTranslationZ() > 0.0f) issueDrawShadowOperation(Matrix4::identity(), handler);
+ issueOperations<DeferOperationHandler>(deferStruct.mRenderer, handler);
+}
+
+void RenderNode::deferNodeInParent(DeferStateStruct& deferStruct, const int level) {
DeferOperationHandler handler(deferStruct, level);
- iterate<DeferOperationHandler>(deferStruct.mRenderer, handler, level);
+ issueOperations<DeferOperationHandler>(deferStruct.mRenderer, handler);
}
class ReplayOperationHandler {
@@ -315,21 +347,31 @@
operation->replay(mReplayStruct, saveCount, mLevel, clipToBounds);
}
inline LinearAllocator& allocator() { return *(mReplayStruct.mAllocator); }
+ inline void startMark(const char* name) {
+ mReplayStruct.mRenderer.startMark(name);
+ }
+ inline void endMark() {
+ mReplayStruct.mRenderer.endMark();
+ DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", level * 2, "", this, mName.string(),
+ mReplayStruct.mDrawGlStatus);
+ }
+ inline int level() { return mLevel; }
+ inline int replayFlags() { return mReplayStruct.mReplayFlags; }
private:
ReplayStateStruct& mReplayStruct;
const int mLevel;
};
-void RenderNode::replay(ReplayStateStruct& replayStruct, const int level) {
+void RenderNode::replayNodeTree(ReplayStateStruct& replayStruct) {
+ ReplayOperationHandler handler(replayStruct, 0);
+ if (properties().getTranslationZ() > 0.0f) issueDrawShadowOperation(Matrix4::identity(), handler);
+ issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
+}
+
+void RenderNode::replayNodeInParent(ReplayStateStruct& replayStruct, const int level) {
ReplayOperationHandler handler(replayStruct, level);
-
- replayStruct.mRenderer.startMark(mName.string());
- iterate<ReplayOperationHandler>(replayStruct.mRenderer, handler, level);
- replayStruct.mRenderer.endMark();
-
- DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", level * 2, "", this, mName.string(),
- replayStruct.mDrawGlStatus);
+ issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
}
void RenderNode::buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes) {
@@ -353,10 +395,42 @@
std::stable_sort(zTranslatedNodes.begin(), zTranslatedNodes.end());
}
+template <class T>
+void RenderNode::issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler) {
+ if (properties().getAlpha() <= 0.0f) return;
+
+ mat4 shadowMatrixXY(transformFromParent);
+ applyViewPropertyTransforms(shadowMatrixXY);
+
+ // Z matrix needs actual 3d transformation, so mapped z values will be correct
+ mat4 shadowMatrixZ(transformFromParent);
+ applyViewPropertyTransforms(shadowMatrixZ, true);
+
+ const SkPath* outlinePath = properties().getOutline().getPath();
+ const RevealClip& revealClip = properties().getRevealClip();
+ const SkPath* revealClipPath = revealClip.hasConvexClip()
+ ? revealClip.getPath() : NULL; // only pass the reveal clip's path if it's convex
+
+ /**
+ * The drawing area of the caster is always the same as the its perimeter (which
+ * the shadow system uses) *except* in the inverse clip case. Inform the shadow
+ * system that the caster's drawing area (as opposed to its perimeter) has been
+ * clipped, so that it knows the caster can't be opaque.
+ */
+ bool casterUnclipped = !revealClip.willClip() || revealClip.hasConvexClip();
+
+ DisplayListOp* shadowOp = new (handler.allocator()) DrawShadowOp(
+ shadowMatrixXY, shadowMatrixZ,
+ properties().getAlpha(), casterUnclipped,
+ properties().getWidth(), properties().getHeight(),
+ outlinePath, revealClipPath);
+ handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
+}
+
#define SHADOW_DELTA 0.1f
template <class T>
-void RenderNode::iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+void RenderNode::issueOperationsOf3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler) {
const int size = zTranslatedNodes.size();
if (size == 0
@@ -366,12 +440,6 @@
return;
}
- int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
- LinearAllocator& alloc = handler.allocator();
- ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, properties().getWidth(), properties().getHeight(),
- SkRegion::kIntersect_Op); // clip to 3d root bounds
- handler(clipOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
-
/**
* Draw shadows and (potential) casters mostly in order, but allow the shadows of casters
* with very similar Z heights to draw together.
@@ -399,21 +467,7 @@
// attempt to render the shadow if the caster about to be drawn is its caster,
// OR if its caster's Z value is similar to the previous potential caster
if (shadowIndex == drawIndex || casterZ - lastCasterZ < SHADOW_DELTA) {
-
- if (caster->properties().getAlpha() > 0.0f) {
- mat4 shadowMatrixXY(casterOp->mTransformFromParent);
- caster->applyViewPropertyTransforms(shadowMatrixXY);
-
- // Z matrix needs actual 3d transformation, so mapped z values will be correct
- mat4 shadowMatrixZ(casterOp->mTransformFromParent);
- caster->applyViewPropertyTransforms(shadowMatrixZ, true);
-
- DisplayListOp* shadowOp = new (alloc) DrawShadowOp(
- shadowMatrixXY, shadowMatrixZ,
- caster->properties().getAlpha(), caster->properties().getOutline().getPath(),
- caster->properties().getWidth(), caster->properties().getHeight());
- handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
- }
+ caster->issueDrawShadowOperation(casterOp->mTransformFromParent, handler);
lastCasterZ = casterZ; // must do this even if current caster not casting a shadow
shadowIndex++;
@@ -436,17 +490,10 @@
renderer.restoreToCount(restoreTo);
drawIndex++;
}
- handler(new (alloc) RestoreToCountOp(rootRestoreTo), PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
template <class T>
-void RenderNode::iterateProjectedChildren(OpenGLRenderer& renderer, T& handler, const int level) {
- int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
- LinearAllocator& alloc = handler.allocator();
- ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, properties().getWidth(), properties().getHeight(),
- SkRegion::kReplace_Op); // clip to projection surface root bounds
- handler(clipOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
-
+void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler) {
for (size_t i = 0; i < mProjectedNodes.size(); i++) {
DrawDisplayListOp* childOp = mProjectedNodes[i];
@@ -458,7 +505,6 @@
childOp->mSkipInOrderDraw = true;
renderer.restoreToCount(restoreTo);
}
- handler(new (alloc) RestoreToCountOp(rootRestoreTo), PROPERTY_SAVECOUNT, properties().getClipToBounds());
}
/**
@@ -471,7 +517,8 @@
* defer vs replay logic, per operation
*/
template <class T>
-void RenderNode::iterate(OpenGLRenderer& renderer, T& handler, const int level) {
+void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
+ const int level = handler.level();
if (CC_UNLIKELY(mDestroyed)) { // temporary debug logging
ALOGW("Error: %s is drawing after destruction", mName.string());
CRASH();
@@ -481,6 +528,8 @@
return;
}
+ handler.startMark(mName.string());
+
#if DEBUG_DISPLAY_LIST
Rect* clipRect = renderer.getClipRect();
DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.0f, %.0f, %.0f",
@@ -496,15 +545,16 @@
DISPLAY_LIST_LOGD("%*sSave %d %d", (level + 1) * 2, "",
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);
- setViewProperties<T>(renderer, handler, level + 1);
+ setViewProperties<T>(renderer, handler);
- bool quickRejected = properties().getClipToBounds() && renderer.quickRejectConservative(0, 0, properties().getWidth(), properties().getHeight());
+ bool quickRejected = properties().getClipToBounds()
+ && renderer.quickRejectConservative(0, 0, properties().getWidth(), properties().getHeight());
if (!quickRejected) {
Vector<ZDrawDisplayListOpPair> zTranslatedNodes;
buildZSortedChildList(zTranslatedNodes);
// for 3d root, draw children with negative z values
- iterate3dChildren(zTranslatedNodes, kNegativeZChildren, renderer, handler);
+ issueOperationsOf3dChildren(zTranslatedNodes, kNegativeZChildren, renderer, handler);
DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
const int saveCountOffset = renderer.getSaveCount() - 1;
@@ -515,23 +565,24 @@
#if DEBUG_DISPLAY_LIST
op->output(level + 1);
#endif
-
logBuffer.writeCommand(level, op->name());
handler(op, saveCountOffset, properties().getClipToBounds());
if (CC_UNLIKELY(i == projectionReceiveIndex && mProjectedNodes.size() > 0)) {
- iterateProjectedChildren(renderer, handler, level);
+ issueOperationsOfProjectedChildren(renderer, handler);
}
}
// for 3d root, draw children with positive z values
- iterate3dChildren(zTranslatedNodes, kPositiveZChildren, renderer, handler);
+ issueOperationsOf3dChildren(zTranslatedNodes, kPositiveZChildren, renderer, handler);
}
DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo);
handler(new (alloc) RestoreToCountOp(restoreTo),
PROPERTY_SAVECOUNT, properties().getClipToBounds());
renderer.setOverrideLayerAlpha(1.0f);
+
+ handler.endMark();
}
} /* namespace uirenderer */
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 756c9444..fb5336d 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -92,8 +92,12 @@
ANDROID_API void setData(DisplayListData* newData);
void computeOrdering();
- void defer(DeferStateStruct& deferStruct, const int level);
- void replay(ReplayStateStruct& replayStruct, const int level);
+
+ void deferNodeTree(DeferStateStruct& deferStruct);
+ void deferNodeInParent(DeferStateStruct& deferStruct, const int level);
+
+ void replayNodeTree(ReplayStateStruct& replayStruct);
+ void replayNodeInParent(ReplayStateStruct& replayStruct, const int level);
ANDROID_API void output(uint32_t level = 1);
@@ -139,6 +143,9 @@
ANDROID_API void updateProperties();
+ // Returns true if this RenderNode or any of its children have functors
+ bool hasFunctors();
+
private:
typedef key_value_pair_t<float, DrawDisplayListOp*> ZDrawDisplayListOpPair;
@@ -161,19 +168,26 @@
const mat4* transformFromProjectionSurface);
template <class T>
- inline void setViewProperties(OpenGLRenderer& renderer, T& handler, const int level);
+ inline void setViewProperties(OpenGLRenderer& renderer, T& handler);
void buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes);
+ template<class T>
+ inline void issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler);
+
template <class T>
- inline void iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+ inline void issueOperationsOf3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler);
template <class T>
- inline void iterateProjectedChildren(OpenGLRenderer& renderer, T& handler, const int level);
+ inline void issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler);
+ /**
+ * Issue the RenderNode's operations into a handler, recursing for subtrees through
+ * DrawDisplayListOp's defer() or replay() methods
+ */
template <class T>
- inline void iterate(OpenGLRenderer& renderer, T& handler, const int level);
+ inline void issueOperations(OpenGLRenderer& renderer, T& handler);
class TextContainer {
public:
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index ca291a6..e7e7768 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -22,6 +22,8 @@
#include <SkCanvas.h>
#include <SkMatrix.h>
+#include <SkPath.h>
+#include <SkPathOps.h>
#include "Matrix.h"
@@ -43,26 +45,24 @@
, mPrevWidth(-1), mPrevHeight(-1)
, mPivotExplicitlySet(false)
, mMatrixDirty(false)
- , mMatrixIsIdentity(true)
, mMatrixFlags(0)
, mCaching(false) {
}
RenderProperties::ComputedFields::ComputedFields()
: mTransformMatrix(NULL)
- , mTransformCamera(NULL)
- , mTransformMatrix3D(NULL) {
+ , mTransformMatrix3D(NULL)
+ , mClipPath(NULL) {
}
RenderProperties::ComputedFields::~ComputedFields() {
delete mTransformMatrix;
- delete mTransformCamera;
delete mTransformMatrix3D;
+ delete mClipPath;
}
RenderProperties::RenderProperties()
- : mCameraDistance(0)
- , mStaticMatrix(NULL)
+ : mStaticMatrix(NULL)
, mAnimationMatrix(NULL) {
}
@@ -78,7 +78,11 @@
setAnimationMatrix(other.getAnimationMatrix());
setCameraDistance(other.getCameraDistance());
- // Update the computed fields
+ // Update the computed clip path
+ updateClipPath();
+
+ // Force recalculation of the matrix, since other's dirty bit may be clear
+ mPrimitiveFields.mMatrixDirty = true;
updateMatrix();
}
return *this;
@@ -101,8 +105,8 @@
ALOGD("%*sTranslate %.2f, %.2f, %.2f",
level * 2, "", mPrimitiveFields.mTranslationX, mPrimitiveFields.mTranslationY, mPrimitiveFields.mTranslationZ);
} else {
- ALOGD("%*sConcatMatrix %p: " MATRIX_4_STRING,
- level * 2, "", mComputedFields.mTransformMatrix, MATRIX_4_ARGS(mComputedFields.mTransformMatrix));
+ ALOGD("%*sConcatMatrix %p: " SK_MATRIX_STRING,
+ level * 2, "", mComputedFields.mTransformMatrix, SK_MATRIX_ARGS(mComputedFields.mTransformMatrix));
}
}
@@ -136,7 +140,7 @@
if (mPrimitiveFields.mMatrixFlags && mPrimitiveFields.mMatrixFlags != TRANSLATION) {
if (!mComputedFields.mTransformMatrix) {
// only allocate a mPrimitiveFields.matrix if we have a complex transform
- mComputedFields.mTransformMatrix = new Matrix4();
+ mComputedFields.mTransformMatrix = new SkMatrix();
}
if (!mPrimitiveFields.mPivotExplicitlySet) {
if (mPrimitiveFields.mWidth != mPrimitiveFields.mPrevWidth || mPrimitiveFields.mHeight != mPrimitiveFields.mPrevHeight) {
@@ -148,38 +152,70 @@
}
if ((mPrimitiveFields.mMatrixFlags & ROTATION_3D) == 0) {
- mComputedFields.mTransformMatrix->loadTranslate(
- mPrimitiveFields.mPivotX + mPrimitiveFields.mTranslationX,
- mPrimitiveFields.mPivotY + mPrimitiveFields.mTranslationY,
- 0);
- mComputedFields.mTransformMatrix->rotate(mPrimitiveFields.mRotation, 0, 0, 1);
- mComputedFields.mTransformMatrix->scale(mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY, 1);
- mComputedFields.mTransformMatrix->translate(-mPrimitiveFields.mPivotX, -mPrimitiveFields.mPivotY);
+ mComputedFields.mTransformMatrix->setTranslate(
+ mPrimitiveFields.mTranslationX, mPrimitiveFields.mTranslationY);
+ mComputedFields.mTransformMatrix->preRotate(mPrimitiveFields.mRotation,
+ mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY);
+ mComputedFields.mTransformMatrix->preScale(
+ mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY,
+ mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY);
} else {
- if (!mComputedFields.mTransformCamera) {
- mComputedFields.mTransformCamera = new Sk3DView();
+ if (!mComputedFields.mTransformMatrix3D) {
mComputedFields.mTransformMatrix3D = new SkMatrix();
}
- SkMatrix transformMatrix;
- transformMatrix.reset();
- mComputedFields.mTransformCamera->save();
- transformMatrix.preScale(mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY, mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY);
- mComputedFields.mTransformCamera->rotateX(mPrimitiveFields.mRotationX);
- mComputedFields.mTransformCamera->rotateY(mPrimitiveFields.mRotationY);
- mComputedFields.mTransformCamera->rotateZ(-mPrimitiveFields.mRotation);
- mComputedFields.mTransformCamera->getMatrix(mComputedFields.mTransformMatrix3D);
+ mComputedFields.mTransformMatrix->reset();
+ mComputedFields.mTransformCamera.save();
+ mComputedFields.mTransformMatrix->preScale(
+ mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY,
+ mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY);
+ mComputedFields.mTransformCamera.rotateX(mPrimitiveFields.mRotationX);
+ mComputedFields.mTransformCamera.rotateY(mPrimitiveFields.mRotationY);
+ mComputedFields.mTransformCamera.rotateZ(-mPrimitiveFields.mRotation);
+ mComputedFields.mTransformCamera.getMatrix(mComputedFields.mTransformMatrix3D);
mComputedFields.mTransformMatrix3D->preTranslate(-mPrimitiveFields.mPivotX, -mPrimitiveFields.mPivotY);
mComputedFields.mTransformMatrix3D->postTranslate(mPrimitiveFields.mPivotX + mPrimitiveFields.mTranslationX,
mPrimitiveFields.mPivotY + mPrimitiveFields.mTranslationY);
- transformMatrix.postConcat(*mComputedFields.mTransformMatrix3D);
- mComputedFields.mTransformCamera->restore();
-
- mComputedFields.mTransformMatrix->load(transformMatrix);
+ mComputedFields.mTransformMatrix->postConcat(*mComputedFields.mTransformMatrix3D);
+ mComputedFields.mTransformCamera.restore();
}
}
mPrimitiveFields.mMatrixDirty = false;
}
}
+void RenderProperties::updateClipPath() {
+ const SkPath* outlineClipPath = mPrimitiveFields.mOutline.willClip()
+ ? mPrimitiveFields.mOutline.getPath() : NULL;
+ const SkPath* revealClipPath = mPrimitiveFields.mRevealClip.getPath();
+
+ if (!outlineClipPath && !revealClipPath) {
+ // mComputedFields.mClipPath doesn't need to be updated, since it won't be used
+ return;
+ }
+
+ if (mComputedFields.mClipPath == NULL) {
+ mComputedFields.mClipPath = new SkPath();
+ }
+ SkPath* clipPath = mComputedFields.mClipPath;
+ mComputedFields.mClipPathOp = SkRegion::kIntersect_Op;
+
+ if (outlineClipPath && revealClipPath) {
+ SkPathOp op = kIntersect_PathOp;
+ if (mPrimitiveFields.mRevealClip.isInverseClip()) {
+ op = kDifference_PathOp; // apply difference step in the Op below, instead of draw time
+ }
+
+ Op(*outlineClipPath, *revealClipPath, op, clipPath);
+ } else if (outlineClipPath) {
+ *clipPath = *outlineClipPath;
+ } else {
+ *clipPath = *revealClipPath;
+ if (mPrimitiveFields.mRevealClip.isInverseClip()) {
+ // apply difference step at draw time
+ mComputedFields.mClipPathOp = SkRegion::kDifference_Op;
+ }
+ }
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 504196d..dd68210 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -22,8 +22,10 @@
#include <SkCamera.h>
#include <SkMatrix.h>
+#include <SkRegion.h>
#include "Rect.h"
+#include "RevealClip.h"
#include "Outline.h"
#define TRANSLATION 0x0001
@@ -34,7 +36,6 @@
class SkBitmap;
class SkPaint;
-class SkRegion;
namespace android {
namespace uirenderer {
@@ -257,20 +258,20 @@
return mPrimitiveFields.mPivotY;
}
+ bool isPivotExplicitlySet() const {
+ return mPrimitiveFields.mPivotExplicitlySet;
+ }
+
void setCameraDistance(float distance) {
- if (distance != mCameraDistance) {
- mCameraDistance = distance;
+ if (distance != getCameraDistance()) {
mPrimitiveFields.mMatrixDirty = true;
- if (!mComputedFields.mTransformCamera) {
- mComputedFields.mTransformCamera = new Sk3DView();
- mComputedFields.mTransformMatrix3D = new SkMatrix();
- }
- mComputedFields.mTransformCamera->setCameraLocation(0, 0, distance);
+ mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance);
}
}
float getCameraDistance() const {
- return mCameraDistance;
+ // TODO: update getCameraLocationZ() to be const
+ return const_cast<Sk3DView*>(&mComputedFields.mTransformCamera)->getCameraLocationZ();
}
void setLeft(int left) {
@@ -395,7 +396,7 @@
return mPrimitiveFields.mMatrixFlags;
}
- const Matrix4* getTransformMatrix() const {
+ const SkMatrix* getTransformMatrix() const {
return mComputedFields.mTransformMatrix;
}
@@ -415,6 +416,10 @@
return mPrimitiveFields.mOutline;
}
+ const RevealClip& getRevealClip() const {
+ return mPrimitiveFields.mRevealClip;
+ }
+
bool getProjectBackwards() const {
return mPrimitiveFields.mProjectBackwards;
}
@@ -423,10 +428,29 @@
ANDROID_API void updateMatrix();
+ ANDROID_API void updateClipPath();
+
+ // signals that mComputedFields.mClipPath is up to date, and should be used for clipping
+ bool hasClippingPath() const {
+ return mPrimitiveFields.mOutline.willClip() || mPrimitiveFields.mRevealClip.willClip();
+ }
+
+ const SkPath* getClippingPath() const {
+ return hasClippingPath() ? mComputedFields.mClipPath : NULL;
+ }
+
+ SkRegion::Op getClippingPathOp() const {
+ return mComputedFields.mClipPathOp;
+ }
+
Outline& mutableOutline() {
return mPrimitiveFields.mOutline;
}
+ RevealClip& mutableRevealClip() {
+ return mPrimitiveFields.mRevealClip;
+ }
+
private:
void onTranslationUpdate() {
mPrimitiveFields.mMatrixDirty = true;
@@ -442,6 +466,7 @@
PrimitiveFields();
Outline mOutline;
+ RevealClip mRevealClip;
bool mClipToBounds;
bool mProjectBackwards;
bool mProjectionReceiver;
@@ -456,13 +481,11 @@
int mPrevWidth, mPrevHeight;
bool mPivotExplicitlySet;
bool mMatrixDirty;
- bool mMatrixIsIdentity;
uint32_t mMatrixFlags;
bool mCaching;
} mPrimitiveFields;
// mCameraDistance isn't in mPrimitiveFields as it has a complex setter
- float mCameraDistance;
SkMatrix* mStaticMatrix;
SkMatrix* mAnimationMatrix;
@@ -477,12 +500,15 @@
* Stores the total transformation of the DisplayList based upon its scalar
* translate/rotate/scale properties.
*
- * In the common translation-only case, the matrix isn't allocated and the mTranslation
- * properties are used directly.
+ * In the common translation-only case, the matrix isn't necessarily allocated,
+ * and the mTranslation properties are used directly.
*/
- Matrix4* mTransformMatrix;
- Sk3DView* mTransformCamera;
+ SkMatrix* mTransformMatrix;
+
+ Sk3DView mTransformCamera;
SkMatrix* mTransformMatrix3D;
+ SkPath* mClipPath; // TODO: remove this, create new ops for efficient/special case clipping
+ SkRegion::Op mClipPathOp;
} mComputedFields;
};
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 5562f34..13a3e8e 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -31,9 +31,9 @@
ALOGD("ResourceCache: cacheReport:");
for (size_t i = 0; i < mCache->size(); ++i) {
ResourceReference* ref = mCache->valueAt(i);
- ALOGD(" ResourceCache: mCache(%d): resource, ref = 0x%p, 0x%p",
+ ALOGD(" ResourceCache: mCache(%zu): resource, ref = 0x%p, 0x%p",
i, mCache->keyAt(i), mCache->valueAt(i));
- ALOGD(" ResourceCache: mCache(%d): refCount, recycled, destroyed, type = %d, %d, %d, %d",
+ ALOGD(" ResourceCache: mCache(%zu): refCount, recycled, destroyed, type = %d, %d, %d, %d",
i, ref->refCount, ref->recycled, ref->destroyed, ref->resourceType);
}
}
diff --git a/libs/hwui/RevealClip.h b/libs/hwui/RevealClip.h
new file mode 100644
index 0000000..ece8498
--- /dev/null
+++ b/libs/hwui/RevealClip.h
@@ -0,0 +1,78 @@
+/*
+ * 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 REVEALCLIP_H
+#define REVEALCLIP_H
+
+#include <SkPath.h>
+
+#include "Rect.h"
+
+namespace android {
+namespace uirenderer {
+
+class RevealClip {
+public:
+ RevealClip()
+ : mShouldClip(false)
+ , mInverseClip(false)
+ , mX(0)
+ , mY(0)
+ , mRadius(0) {}
+
+ void set(bool shouldClip, bool inverseClip, float x, float y, float radius) {
+ mShouldClip = shouldClip;
+ mInverseClip = inverseClip;
+ mX = x;
+ mY = y;
+ mRadius = radius;
+
+ mPath.rewind();
+ if (mShouldClip) {
+ mPath.addCircle(x, y, radius);
+ }
+ }
+
+ bool hasConvexClip() const {
+ return mShouldClip && !mInverseClip;
+ }
+
+ bool isInverseClip() const {
+ return mInverseClip;
+ }
+
+ bool willClip() const {
+ return mShouldClip;
+ }
+
+ const SkPath* getPath() const {
+ if (!mShouldClip) return NULL;
+
+ return &mPath;
+ }
+
+private:
+ bool mShouldClip;
+ bool mInverseClip;
+ float mX;
+ float mY;
+ float mRadius;
+ SkPath mPath;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* REVEALCLIP_H */
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index cc6d0cd..5bdb18a 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -108,7 +108,7 @@
* Returns the current clip in local coordinates. The clip rect is
* transformed by the inverse transform matrix.
*/
- const Rect& getLocalClip();
+ ANDROID_API const Rect& getLocalClip();
/**
* Resets the clip to the specified rect.
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index b3b4173..fa82627 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -82,6 +82,8 @@
// Returns true on success, false on failure
void initialize();
+ bool hasContext();
+
void usePBufferSurface();
EGLSurface createSurface(EGLNativeWindowType window);
void destroySurface(EGLSurface surface);
@@ -138,7 +140,7 @@
}
void GlobalContext::initialize() {
- if (mEglDisplay != EGL_NO_DISPLAY) return;
+ if (hasContext()) return;
mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
@@ -157,6 +159,10 @@
initAtlas();
}
+bool GlobalContext::hasContext() {
+ return mEglDisplay != EGL_NO_DISPLAY;
+}
+
void GlobalContext::loadConfig() {
EGLint swapBehavior = mCanSetDirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
EGLint attribs[] = {
@@ -392,8 +398,6 @@
LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE,
"drawDisplayList called on a context with no canvas or surface!");
- displayList->updateProperties();
-
EGLint width, height;
mGlobalContext->beginFrame(mEglSurface, &width, &height);
if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) {
@@ -413,7 +417,6 @@
Rect outBounds;
status |= mCanvas->drawDisplayList(displayList, outBounds);
- handleFunctorStatus(status, outBounds);
// TODO: Draw debug info
// TODO: Performance tracking
@@ -443,6 +446,15 @@
mCanvas->detachFunctor(functor);
}
+void CanvasContext::invokeFunctor(Functor* functor) {
+ DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
+ if (mGlobalContext->hasContext()) {
+ requireGlContext();
+ mode = DrawGlInfo::kModeProcess;
+ }
+ (*functor)(mode, NULL);
+}
+
void CanvasContext::invokeFunctors() {
mInvokeFunctorsPending = false;
@@ -450,22 +462,7 @@
makeCurrent();
Rect dirty;
- int status = mCanvas->invokeFunctors(dirty);
- handleFunctorStatus(status, dirty);
-}
-
-void CanvasContext::handleFunctorStatus(int status, const Rect& redrawClip) {
- if (status & DrawGlInfo::kStatusDraw) {
- // TODO: Invalidate the redrawClip
- // Do we need to post to ViewRootImpl like the current renderer?
- // Can we just enqueue ourselves to re-invoke the same display list?
- // Something else entirely? Does ChromiumView still want this in a
- // RenderThread world?
- }
-
- if (status & DrawGlInfo::kStatusInvoke) {
- queueFunctorsTask();
- }
+ mCanvas->invokeFunctors(dirty);
}
void CanvasContext::removeFunctorsTask() {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index e3fdf97..eb9096d 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -72,6 +72,7 @@
void attachFunctor(Functor* functor);
void detachFunctor(Functor* functor);
+ void invokeFunctor(Functor* functor);
void runWithGlContext(RenderTask* task);
@@ -82,7 +83,6 @@
friend class InvokeFunctorsTask;
void invokeFunctors();
- void handleFunctorStatus(int status, const Rect& redrawClip);
void removeFunctorsTask();
void queueFunctorsTask(int delayMs = FUNCTOR_PROCESS_DELAY);
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
new file mode 100644
index 0000000..1e9089a
--- /dev/null
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -0,0 +1,143 @@
+/*
+ * 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 ATRACE_TAG ATRACE_TAG_VIEW
+
+#include "DrawFrameTask.h"
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include "../DisplayList.h"
+#include "../RenderNode.h"
+#include "CanvasContext.h"
+#include "RenderThread.h"
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+DrawFrameTask::DrawFrameTask() : mContext(0), mRenderNode(0) {
+}
+
+DrawFrameTask::~DrawFrameTask() {
+}
+
+void DrawFrameTask::setContext(CanvasContext* context) {
+ mContext = context;
+}
+
+void DrawFrameTask::setDisplayListData(RenderNode* renderNode, DisplayListData* newData) {
+ SetDisplayListData setter;
+ setter.targetNode = renderNode;
+ setter.newData = newData;
+ mDisplayListDataUpdates.push(setter);
+}
+
+void DrawFrameTask::addLayer(DeferredLayerUpdater* layer) {
+ mLayers.push(layer);
+}
+
+void DrawFrameTask::removeLayer(DeferredLayerUpdater* layer) {
+ for (size_t i = 0; i < mLayers.size(); i++) {
+ if (mLayers[i] == layer) {
+ mLayers.removeAt(i);
+ break;
+ }
+ }
+}
+
+void DrawFrameTask::setRenderNode(RenderNode* renderNode) {
+ mRenderNode = renderNode;
+}
+
+void DrawFrameTask::setDirty(int left, int top, int right, int bottom) {
+ mDirty.set(left, top, right, bottom);
+}
+
+void DrawFrameTask::drawFrame(RenderThread* renderThread) {
+ LOG_ALWAYS_FATAL_IF(!mRenderNode, "Cannot drawFrame with no render node!");
+ LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
+
+ AutoMutex _lock(mLock);
+ renderThread->queue(this);
+ mSignal.wait(mLock);
+
+ // Reset the single-frame data
+ mDirty.setEmpty();
+ mRenderNode = 0;
+}
+
+void DrawFrameTask::run() {
+ ATRACE_NAME("DrawFrame");
+
+ syncFrameState();
+
+ // Grab a copy of everything we need
+ Rect dirtyCopy(mDirty);
+ RenderNode* renderNode = mRenderNode;
+ CanvasContext* context = mContext;
+
+ // This is temporary until WebView has a solution for syncing frame state
+ bool canUnblockUiThread = !requiresSynchronousDraw(renderNode);
+
+ // From this point on anything in "this" is *UNSAFE TO ACCESS*
+ if (canUnblockUiThread) {
+ unblockUiThread();
+ }
+
+ drawRenderNode(context, renderNode, &dirtyCopy);
+
+ if (!canUnblockUiThread) {
+ unblockUiThread();
+ }
+}
+
+void DrawFrameTask::syncFrameState() {
+ ATRACE_CALL();
+
+ for (size_t i = 0; i < mDisplayListDataUpdates.size(); i++) {
+ const SetDisplayListData& setter = mDisplayListDataUpdates[i];
+ setter.targetNode->setData(setter.newData);
+ }
+ mDisplayListDataUpdates.clear();
+
+ mContext->processLayerUpdates(&mLayers);
+ mRenderNode->updateProperties();
+}
+
+void DrawFrameTask::unblockUiThread() {
+ AutoMutex _lock(mLock);
+ mSignal.signal();
+}
+
+void DrawFrameTask::drawRenderNode(CanvasContext* context, RenderNode* renderNode, Rect* dirty) {
+ ATRACE_CALL();
+
+ if (dirty->bottom == -1 && dirty->left == -1
+ && dirty->top == -1 && dirty->right == -1) {
+ dirty = 0;
+ }
+ context->drawDisplayList(renderNode, dirty);
+}
+
+bool DrawFrameTask::requiresSynchronousDraw(RenderNode* renderNode) {
+ return renderNode->hasFunctors();
+}
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
new file mode 100644
index 0000000..5450dd5
--- /dev/null
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -0,0 +1,98 @@
+/*
+ * 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 DRAWFRAMETASK_H
+#define DRAWFRAMETASK_H
+
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <utils/Vector.h>
+
+#include "RenderTask.h"
+
+#include "../Rect.h"
+
+namespace android {
+namespace uirenderer {
+
+class DeferredLayerUpdater;
+class DisplayListData;
+class RenderNode;
+
+namespace renderthread {
+
+class CanvasContext;
+class RenderThread;
+
+struct SetDisplayListData {
+ RenderNode* targetNode;
+ DisplayListData* newData;
+};
+
+/*
+ * This is a special Super Task. It is re-used multiple times by RenderProxy,
+ * and contains state (such as layer updaters & new DisplayListDatas) that is
+ * tracked across many frames not just a single frame.
+ * It is the sync-state task, and will kick off the post-sync draw
+ */
+class DrawFrameTask : public RenderTask {
+public:
+ DrawFrameTask();
+ virtual ~DrawFrameTask();
+
+ void setContext(CanvasContext* context);
+
+ void setDisplayListData(RenderNode* renderNode, DisplayListData* newData);
+ void addLayer(DeferredLayerUpdater* layer);
+ void removeLayer(DeferredLayerUpdater* layer);
+
+ void setRenderNode(RenderNode* renderNode);
+ void setDirty(int left, int top, int right, int bottom);
+ void drawFrame(RenderThread* renderThread);
+
+ virtual void run();
+
+private:
+ void syncFrameState();
+ void unblockUiThread();
+ static void drawRenderNode(CanvasContext* context, RenderNode* renderNode, Rect* dirty);
+
+ // This checks to see if there are any drawGlFunctors which would require
+ // a synchronous drawRenderNode()
+ static bool requiresSynchronousDraw(RenderNode* renderNode);
+
+ Mutex mLock;
+ Condition mSignal;
+
+ CanvasContext* mContext;
+
+ /*********************************************
+ * Single frame data
+ *********************************************/
+ RenderNode* mRenderNode;
+ Rect mDirty;
+ Vector<SetDisplayListData> mDisplayListDataUpdates;
+
+ /*********************************************
+ * Multi frame data
+ *********************************************/
+ Vector<DeferredLayerUpdater*> mLayers;
+};
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* DRAWFRAMETASK_H */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 93360fc..cd711b0 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -61,6 +61,7 @@
SETUP_TASK(createContext);
args->translucent = translucent;
mContext = (CanvasContext*) postAndWait(task);
+ mDrawFrameTask.setContext(mContext);
}
RenderProxy::~RenderProxy() {
@@ -77,7 +78,10 @@
SETUP_TASK(destroyContext);
args->context = mContext;
mContext = 0;
- post(task);
+ mDrawFrameTask.setContext(0);
+ // This is also a fence as we need to be certain that there are no
+ // outstanding mDrawFrame tasks posted before it is destroyed
+ postAndWait(task);
}
}
@@ -117,41 +121,15 @@
post(task);
}
-CREATE_BRIDGE3(setDisplayListData, CanvasContext* context, RenderNode* displayList,
- DisplayListData* newData) {
- args->context->setDisplayListData(args->displayList, args->newData);
- return NULL;
-}
-
-void RenderProxy::setDisplayListData(RenderNode* displayList, DisplayListData* newData) {
- SETUP_TASK(setDisplayListData);
- args->context = mContext;
- args->displayList = displayList;
- args->newData = newData;
- post(task);
-}
-
-CREATE_BRIDGE4(drawDisplayList, CanvasContext* context, RenderNode* displayList,
- Rect dirty, const Vector<DeferredLayerUpdater*>* layerUpdates) {
- Rect* dirty = &args->dirty;
- if (dirty->bottom == -1 && dirty->left == -1 &&
- dirty->top == -1 && dirty->right == -1) {
- dirty = 0;
- }
- args->context->processLayerUpdates(args->layerUpdates);
- args->context->drawDisplayList(args->displayList, dirty);
- return NULL;
+void RenderProxy::setDisplayListData(RenderNode* renderNode, DisplayListData* newData) {
+ mDrawFrameTask.setDisplayListData(renderNode, newData);
}
void RenderProxy::drawDisplayList(RenderNode* displayList,
int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom) {
- SETUP_TASK(drawDisplayList);
- args->context = mContext;
- args->displayList = displayList;
- args->dirty.set(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
- args->layerUpdates = &mLayers;
- // TODO: Switch to post() once some form of thread safety strategy is in place
- postAndWait(task);
+ mDrawFrameTask.setRenderNode(displayList);
+ mDrawFrameTask.setDirty(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
+ mDrawFrameTask.drawFrame(&mRenderThread);
}
CREATE_BRIDGE1(destroyCanvas, CanvasContext* context) {
@@ -189,6 +167,22 @@
post(task);
}
+CREATE_BRIDGE2(invokeFunctor, CanvasContext* context, Functor* functor) {
+ args->context->invokeFunctor(args->functor);
+ return NULL;
+}
+
+void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
+ SETUP_TASK(invokeFunctor);
+ args->context = mContext;
+ args->functor = functor;
+ if (waitForCompletion) {
+ postAndWait(task);
+ } else {
+ post(task);
+ }
+}
+
CREATE_BRIDGE2(runWithGlContext, CanvasContext* context, RenderTask* task) {
args->context->runWithGlContext(args->task);
return NULL;
@@ -205,9 +199,7 @@
Layer* layer = LayerRenderer::createRenderLayer(args->width, args->height);
if (!layer) return 0;
- OpenGLRenderer* renderer = new LayerRenderer(layer);
- renderer->initProperties();
- return new DeferredLayerUpdater(layer, renderer);
+ return new DeferredLayerUpdater(layer);
}
DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height) {
@@ -216,7 +208,7 @@
args->height = height;
void* retval = postAndWait(task);
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
- mLayers.push(layer);
+ mDrawFrameTask.addLayer(layer);
return layer;
}
@@ -230,7 +222,7 @@
SETUP_TASK(createTextureLayer);
void* retval = postAndWait(task);
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
- mLayers.push(layer);
+ mDrawFrameTask.addLayer(layer);
return layer;
}
@@ -254,12 +246,7 @@
}
void RenderProxy::destroyLayer(DeferredLayerUpdater* layer) {
- for (size_t i = 0; i < mLayers.size(); i++) {
- if (mLayers[i] == layer) {
- mLayers.removeAt(i);
- break;
- }
- }
+ mDrawFrameTask.removeLayer(layer);
SETUP_TASK(destroyLayer);
args->layer = layer->detachBackingLayer();
post(task);
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 73e9805..f1ca534 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -28,6 +28,8 @@
#include <utils/StrongPointer.h>
#include <utils/Vector.h>
+#include "DrawFrameTask.h"
+
namespace android {
namespace uirenderer {
@@ -60,13 +62,14 @@
ANDROID_API bool initialize(EGLNativeWindowType window);
ANDROID_API void updateSurface(EGLNativeWindowType window);
ANDROID_API void setup(int width, int height);
- ANDROID_API void setDisplayListData(RenderNode* displayList, DisplayListData* newData);
+ ANDROID_API void setDisplayListData(RenderNode* renderNode, DisplayListData* newData);
ANDROID_API void drawDisplayList(RenderNode* displayList,
int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
ANDROID_API void destroyCanvas();
ANDROID_API void attachFunctor(Functor* functor);
ANDROID_API void detachFunctor(Functor* functor);
+ ANDROID_API void invokeFunctor(Functor* functor, bool waitForCompletion);
ANDROID_API void runWithGlContext(RenderTask* task);
@@ -79,11 +82,11 @@
RenderThread& mRenderThread;
CanvasContext* mContext;
+ DrawFrameTask mDrawFrameTask;
+
Mutex mSyncMutex;
Condition mSyncCondition;
- Vector<DeferredLayerUpdater*> mLayers;
-
void destroyContext();
MethodInvokeRenderTask* createTask(RunnableMethod method);
diff --git a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c
index 06b477f..57c0320 100644
--- a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c
+++ b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c
@@ -32,7 +32,7 @@
struct usb_device *sDevice = NULL;
static void* read_thread(void* arg) {
- int endpoint = (int)arg;
+ int endpoint = (int)(uintptr_t)arg;
int ret = 0;
while (sDevice && ret >= 0) {
@@ -52,7 +52,7 @@
}
static void* write_thread(void* arg) {
- int endpoint = (int)arg;
+ int endpoint = (int)(uintptr_t)arg;
int ret = 0;
while (ret >= 0) {
@@ -136,11 +136,11 @@
}
if ((ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
- pthread_create(&th, NULL, read_thread, (void *)ep1->bEndpointAddress);
- pthread_create(&th, NULL, write_thread, (void *)ep2->bEndpointAddress);
+ pthread_create(&th, NULL, read_thread, (void *)(uintptr_t)ep1->bEndpointAddress);
+ pthread_create(&th, NULL, write_thread, (void *)(uintptr_t)ep2->bEndpointAddress);
} else {
- pthread_create(&th, NULL, read_thread, (void *)ep2->bEndpointAddress);
- pthread_create(&th, NULL, write_thread, (void *)ep1->bEndpointAddress);
+ pthread_create(&th, NULL, read_thread, (void *)(uintptr_t)ep2->bEndpointAddress);
+ pthread_create(&th, NULL, write_thread, (void *)(uintptr_t)ep1->bEndpointAddress);
}
} else {
printf("Found possible android device - attempting to switch to accessory mode\n");
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 26e9cc5..04c6e97 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -56,7 +56,7 @@
/** Default audio channel mask */
public static final int CHANNEL_OUT_DEFAULT = 1;
- // Channel mask definitions below are translated to the native values defined in
+ // Output channel mask definitions below are translated to the native values defined in
// in /system/core/include/system/audio.h in the JNI code of AudioTrack
public static final int CHANNEL_OUT_FRONT_LEFT = 0x4;
public static final int CHANNEL_OUT_FRONT_RIGHT = 0x8;
@@ -94,17 +94,21 @@
CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_BACK_CENTER);
public static final int CHANNEL_OUT_5POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT);
+ // different from AUDIO_CHANNEL_OUT_7POINT1
public static final int CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER);
/** @hide */
+ // matches AUDIO_CHANNEL_OUT_7POINT1
public static final int CHANNEL_OUT_7POINT1_SURROUND = (
CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_FRONT_RIGHT |
CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT |
CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
CHANNEL_OUT_LOW_FREQUENCY);
+ // CHANNEL_OUT_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_OUT_ALL
public static final int CHANNEL_IN_DEFAULT = 1;
+ // These directly match native
public static final int CHANNEL_IN_LEFT = 0x4;
public static final int CHANNEL_IN_RIGHT = 0x8;
public static final int CHANNEL_IN_FRONT = 0x10;
@@ -121,5 +125,8 @@
public static final int CHANNEL_IN_VOICE_DNLINK = 0x8000;
public static final int CHANNEL_IN_MONO = CHANNEL_IN_FRONT;
public static final int CHANNEL_IN_STEREO = (CHANNEL_IN_LEFT | CHANNEL_IN_RIGHT);
+ /** @hide */
+ public static final int CHANNEL_IN_FRONT_BACK = CHANNEL_IN_FRONT | CHANNEL_IN_BACK;
+ // CHANNEL_IN_ALL is not yet defined; if added then it should match AUDIO_CHANNEL_IN_ALL
}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index fe510f6..4bd5a80 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -43,6 +43,7 @@
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.database.ContentObserver;
+import android.hardware.usb.UsbManager;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.os.Binder;
@@ -528,6 +529,7 @@
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
+ intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
// TODO merge orientation and rotation
@@ -1689,7 +1691,7 @@
private static final String ASSET_FILE_VERSION = "1.0";
private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
- private static final int SOUND_EFECTS_LOAD_TIMEOUT_MS = 5000;
+ private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000;
class LoadSoundEffectReply {
public int mStatus = 1;
@@ -1801,7 +1803,7 @@
sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
while ((reply.mStatus == 1) && (attempts-- > 0)) {
try {
- reply.wait(SOUND_EFECTS_LOAD_TIMEOUT_MS);
+ reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
} catch (InterruptedException e) {
Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
}
@@ -3289,7 +3291,7 @@
while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
try {
// Wait for mSoundPoolCallBack to be set by the other thread
- mSoundEffectsLock.wait(SOUND_EFECTS_LOAD_TIMEOUT_MS);
+ mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
} catch (InterruptedException e) {
Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
}
@@ -3353,7 +3355,7 @@
status = 1;
while ((status == 1) && (attempts-- > 0)) {
try {
- mSoundEffectsLock.wait(SOUND_EFECTS_LOAD_TIMEOUT_MS);
+ mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
status = mSoundPoolCallBack.status();
} catch (InterruptedException e) {
Log.w(TAG, "Interrupted while waiting sound pool callback.");
@@ -3975,7 +3977,8 @@
(device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) {
setBluetoothA2dpOnInt(true);
}
- boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0);
+ boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0) ||
+ ((device & AudioSystem.DEVICE_IN_ALL_USB) != 0);
handleDeviceConnection((state == 1), device, (isUsb ? name : ""));
if (state != 0) {
if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
@@ -4083,18 +4086,31 @@
} else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ||
action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) {
state = intent.getIntExtra("state", 0);
+
int alsaCard = intent.getIntExtra("card", -1);
int alsaDevice = intent.getIntExtra("device", -1);
+ boolean hasPlayback = intent.getBooleanExtra("hasPlayback", false);
+ boolean hasCapture = intent.getBooleanExtra("hasCapture", false);
+ boolean hasMIDI = intent.getBooleanExtra("hasMIDI", false);
+
String params = (alsaCard == -1 && alsaDevice == -1 ? ""
: "card=" + alsaCard + ";device=" + alsaDevice);
+
+ //TODO(pmclean) - Ignore for now the hasPlayback & hasCapture flags since we
+ // still need to call setWiredDeviceConnectionState() on disconnect (when we
+ // don't have card/device files to parse for this info). We will need to store
+ // that info here when we get smarter about multiple USB card/devices.
+ // Playback Device
device = action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
AudioSystem.DEVICE_OUT_USB_ACCESSORY : AudioSystem.DEVICE_OUT_USB_DEVICE;
- Log.v(TAG, "Broadcast Receiver: Got "
- + (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
- "ACTION_USB_AUDIO_ACCESSORY_PLUG" : "ACTION_USB_AUDIO_DEVICE_PLUG")
- + ", state = " + state + ", card: " + alsaCard + ", device: " + alsaDevice);
setWiredDeviceConnectionState(device, state, params);
- } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
+
+ // Capture Device
+ device = action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
+ AudioSystem.DEVICE_IN_USB_ACCESSORY : AudioSystem.DEVICE_IN_USB_DEVICE;
+ setWiredDeviceConnectionState(device, state, params);
+ }
+ else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
boolean broadcast = false;
int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
synchronized (mScoClients) {
@@ -4199,7 +4215,7 @@
mStreamStates[AudioSystem.STREAM_MUSIC], 0);
}
}
- }
+ } // end class AudioServiceBroadcastReceiver
//==========================================================================================
// RemoteControlDisplay / RemoteControlClient / Remote info
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 9c67bae..327c10c 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -288,6 +288,8 @@
DEVICE_IN_USB_DEVICE |
DEVICE_IN_DEFAULT);
public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+ public static final int DEVICE_IN_ALL_USB = (DEVICE_IN_USB_ACCESSORY |
+ DEVICE_IN_USB_DEVICE);
// device states, must match AudioSystem::device_connection_state
public static final int DEVICE_STATE_UNAVAILABLE = 0;
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 40c6797..57bc171 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1321,7 +1321,7 @@
*
* @param level send level scalar
* @return error code or success, see {@link #SUCCESS},
- * {@link #ERROR_INVALID_OPERATION}
+ * {@link #ERROR_INVALID_OPERATION}, {@link #ERROR}
*/
public int setAuxEffectSendLevel(float level) {
if (isRestricted()) {
@@ -1337,8 +1337,8 @@
if (level > getMaxVolume()) {
level = getMaxVolume();
}
- native_setAuxEffectSendLevel(level);
- return SUCCESS;
+ int err = native_setAuxEffectSendLevel(level);
+ return err == 0 ? SUCCESS : ERROR;
}
//---------------------------------------------------------
@@ -1508,7 +1508,7 @@
int sampleRateInHz, int channelConfig, int audioFormat);
private native final int native_attachAuxEffect(int effectId);
- private native final void native_setAuxEffectSendLevel(float level);
+ private native final int native_setAuxEffectSendLevel(float level);
//---------------------------------------------------------
// Utility methods
diff --git a/media/java/android/media/MediaController.java b/media/java/android/media/MediaController.java
deleted file mode 100644
index 6e3a9b3..0000000
--- a/media/java/android/media/MediaController.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * 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.media;
-
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.media.MediaFocusControl.RcClientDeathHandler;
-import android.os.IBinder;
-import android.os.IBinder.DeathRecipient;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.io.PrintWriter;
-
-/**
- * @hide
- * Class to handle all the information about a media player, encapsulating information
- * about its use RemoteControlClient, playback type and volume... The lifecycle of each
- * instance is managed by android.media.MediaFocusControl, from its addition to the player stack
- * stack to its release.
- */
-class MediaController implements DeathRecipient {
-
- // on purpose not using this classe's name, as it will only be used from MediaFocusControl
- private static final String TAG = "MediaFocusControl";
- private static final boolean DEBUG = false;
-
- /**
- * A global counter for RemoteControlClient identifiers
- */
- private static int sLastRccId = 0;
-
- //FIXME should be final static
- public MediaFocusControl mController;
-
- /**
- * The target for the ACTION_MEDIA_BUTTON events.
- * Always non null.
- */
- final public PendingIntent mMediaIntent;
- /**
- * The registered media button event receiver.
- * Always non null.
- */
- final public ComponentName mReceiverComponent;
-
- public int mRccId = RemoteControlClient.RCSE_ID_UNREGISTERED;
-
- public IBinder mToken;
- public String mCallingPackageName;
- public int mCallingUid;
- /**
- * Provides access to the information to display on the remote control.
- * May be null (when a media button event receiver is registered,
- * but no remote control client has been registered) */
- public IRemoteControlClient mRcClient;
- public RcClientDeathHandler mRcClientDeathHandler;
- /**
- * Information only used for non-local playback
- */
- public int mPlaybackType;
- public int mPlaybackVolume;
- public int mPlaybackVolumeMax;
- public int mPlaybackVolumeHandling;
- public int mPlaybackStream;
- public RccPlaybackState mPlaybackState;
- public IRemoteVolumeObserver mRemoteVolumeObs;
-
-
- protected static class RccPlaybackState {
- public int mState;
- public long mPositionMs;
- public float mSpeed;
-
- public RccPlaybackState(int state, long positionMs, float speed) {
- mState = state;
- mPositionMs = positionMs;
- mSpeed = speed;
- }
-
- public void reset() {
- mState = RemoteControlClient.PLAYSTATE_STOPPED;
- mPositionMs = RemoteControlClient.PLAYBACK_POSITION_INVALID;
- mSpeed = RemoteControlClient.PLAYBACK_SPEED_1X;
- }
-
- @Override
- public String toString() {
- return stateToString() + ", " + posToString() + ", " + mSpeed + "X";
- }
-
- private String posToString() {
- if (mPositionMs == RemoteControlClient.PLAYBACK_POSITION_INVALID) {
- return "PLAYBACK_POSITION_INVALID";
- } else if (mPositionMs == RemoteControlClient.PLAYBACK_POSITION_ALWAYS_UNKNOWN) {
- return "PLAYBACK_POSITION_ALWAYS_UNKNOWN";
- } else {
- return (String.valueOf(mPositionMs) + "ms");
- }
- }
-
- private String stateToString() {
- switch (mState) {
- case RemoteControlClient.PLAYSTATE_NONE:
- return "PLAYSTATE_NONE";
- case RemoteControlClient.PLAYSTATE_STOPPED:
- return "PLAYSTATE_STOPPED";
- case RemoteControlClient.PLAYSTATE_PAUSED:
- return "PLAYSTATE_PAUSED";
- case RemoteControlClient.PLAYSTATE_PLAYING:
- return "PLAYSTATE_PLAYING";
- case RemoteControlClient.PLAYSTATE_FAST_FORWARDING:
- return "PLAYSTATE_FAST_FORWARDING";
- case RemoteControlClient.PLAYSTATE_REWINDING:
- return "PLAYSTATE_REWINDING";
- case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS:
- return "PLAYSTATE_SKIPPING_FORWARDS";
- case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS:
- return "PLAYSTATE_SKIPPING_BACKWARDS";
- case RemoteControlClient.PLAYSTATE_BUFFERING:
- return "PLAYSTATE_BUFFERING";
- case RemoteControlClient.PLAYSTATE_ERROR:
- return "PLAYSTATE_ERROR";
- default:
- return "[invalid playstate]";
- }
- }
- }
-
-
- void dump(PrintWriter pw) {
- // FIXME to implement, remove dump from MediaFocusControl that accesses private members
- }
-
- public void resetPlaybackInfo() {
- mPlaybackType = RemoteControlClient.PLAYBACK_TYPE_LOCAL;
- mPlaybackVolume = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME;
- mPlaybackVolumeMax = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME;
- mPlaybackVolumeHandling = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME_HANDLING;
- mPlaybackStream = AudioManager.STREAM_MUSIC;
- mPlaybackState.reset();
- mRemoteVolumeObs = null;
- }
-
- /** precondition: mediaIntent != null */
- public MediaController(MediaFocusControl controller, PendingIntent mediaIntent,
- ComponentName eventReceiver, IBinder token) {
- mController = controller;
- mMediaIntent = mediaIntent;
- mReceiverComponent = eventReceiver;
- mToken = token;
- mCallingUid = -1;
- mRcClient = null;
- mRccId = ++sLastRccId;
- mPlaybackState = new RccPlaybackState(
- RemoteControlClient.PLAYSTATE_STOPPED,
- RemoteControlClient.PLAYBACK_POSITION_INVALID,
- RemoteControlClient.PLAYBACK_SPEED_1X);
-
- resetPlaybackInfo();
- if (mToken != null) {
- try {
- mToken.linkToDeath(this, 0);
- } catch (RemoteException e) {
- //FIXME do not access the event handler directly
- mController.mEventHandler.post(new Runnable() {
- @Override public void run() {
- mController.unregisterMediaButtonIntent(mMediaIntent);
- }
- });
- }
- }
- }
-
- public void unlinkToRcClientDeath() {
- if ((mRcClientDeathHandler != null) && (mRcClientDeathHandler.mCb != null)) {
- try {
- mRcClientDeathHandler.mCb.unlinkToDeath(mRcClientDeathHandler, 0);
- mRcClientDeathHandler = null;
- } catch (java.util.NoSuchElementException e) {
- // not much we can do here
- Log.e(TAG, "Error in unlinkToRcClientDeath()", e);
- }
- }
- }
-
- // FIXME rename to "release"? (as in FocusRequester class)
- public void destroy() {
- unlinkToRcClientDeath();
- if (mToken != null) {
- mToken.unlinkToDeath(this, 0);
- mToken = null;
- }
- }
-
- @Override
- public void binderDied() {
- mController.unregisterMediaButtonIntent(mMediaIntent);
- }
-
- @Override
- protected void finalize() throws Throwable {
- destroy(); // unlink exception handled inside method
- super.finalize();
- }
-}
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 7170ffb..c016d08 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -1,4 +1,4 @@
-/*
+ /*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,11 +20,14 @@
import java.util.UUID;
import java.util.HashMap;
import java.util.List;
+import android.os.Binder;
+import android.os.Debug;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.util.Log;
+import android.content.Context;
/**
* MediaDrm can be used to obtain keys for decrypting protected media streams, in
@@ -101,6 +104,20 @@
private long mNativeContext;
/**
+ * Specify no certificate type
+ *
+ * @hide - not part of the public API at this time
+ */
+ public static final int CERTIFICATE_TYPE_NONE = 0;
+
+ /**
+ * Specify X.509 certificate type
+ *
+ * @hide - not part of the public API at this time
+ */
+ public static final int CERTIFICATE_TYPE_X509 = 1;
+
+ /**
* Query if the given scheme identified by its UUID is supported on
* this device.
* @param uuid The UUID of the crypto scheme.
@@ -316,6 +333,9 @@
* Contains the opaque data an app uses to request keys from a license server
*/
public final static class KeyRequest {
+ private byte[] mData;
+ private String mDefaultUrl;
+
KeyRequest() {}
/**
@@ -329,9 +349,6 @@
* server URL from other sources.
*/
public String getDefaultUrl() { return mDefaultUrl; }
-
- private byte[] mData;
- private String mDefaultUrl;
};
/**
@@ -456,7 +473,12 @@
* is returned in ProvisionRequest.data. The recommended URL to deliver the provision
* request to is returned in ProvisionRequest.defaultUrl.
*/
- public native ProvisionRequest getProvisionRequest();
+ public ProvisionRequest getProvisionRequest() {
+ return getProvisionRequestNative(CERTIFICATE_TYPE_NONE, "");
+ }
+
+ private native ProvisionRequest getProvisionRequestNative(int certType,
+ String certAuthority);
/**
* After a provision response is received by the app, it is provided to the DRM
@@ -468,7 +490,12 @@
* @throws DeniedByServerException if the response indicates that the
* server rejected the request
*/
- public native void provideProvisionResponse(byte[] response)
+ public void provideProvisionResponse(byte[] response)
+ throws DeniedByServerException {
+ provideProvisionResponseNative(response);
+ }
+
+ private native Certificate provideProvisionResponseNative(byte[] response)
throws DeniedByServerException;
/**
@@ -683,6 +710,120 @@
return new CryptoSession(this, sessionId, cipherAlgorithm, macAlgorithm);
}
+ /**
+ * Contains the opaque data an app uses to request a certificate from a provisioning
+ * server
+ *
+ * @hide - not part of the public API at this time
+ */
+ public final static class CertificateRequest {
+ private byte[] mData;
+ private String mDefaultUrl;
+
+ CertificateRequest(byte[] data, String defaultUrl) {
+ mData = data;
+ mDefaultUrl = defaultUrl;
+ }
+
+ /**
+ * Get the opaque message data
+ */
+ public byte[] getData() { return mData; }
+
+ /**
+ * Get the default URL to use when sending the certificate request
+ * message to a server, if known. The app may prefer to use a different
+ * certificate server URL obtained from other sources.
+ */
+ public String getDefaultUrl() { return mDefaultUrl; }
+ }
+
+ /**
+ * Generate a certificate request, specifying the certificate type
+ * and authority. The response received should be passed to
+ * provideCertificateResponse.
+ *
+ * @param certType Specifies the certificate type.
+ *
+ * @param certAuthority is passed to the certificate server to specify
+ * the chain of authority.
+ *
+ * @hide - not part of the public API at this time
+ */
+ public CertificateRequest getCertificateRequest(int certType,
+ String certAuthority)
+ {
+ ProvisionRequest provisionRequest = getProvisionRequestNative(certType, certAuthority);
+ return new CertificateRequest(provisionRequest.getData(),
+ provisionRequest.getDefaultUrl());
+ }
+
+ /**
+ * Contains the wrapped private key and public certificate data associated
+ * with a certificate.
+ *
+ * @hide - not part of the public API at this time
+ */
+ public final static class Certificate {
+ Certificate() {}
+
+ /**
+ * Get the wrapped private key data
+ */
+ public byte[] getWrappedPrivateKey() { return mWrappedKey; }
+
+ /**
+ * Get the PEM-encoded certificate chain
+ */
+ public byte[] getContent() { return mCertificateData; }
+
+ private byte[] mWrappedKey;
+ private byte[] mCertificateData;
+ }
+
+
+ /**
+ * Process a response from the certificate server. The response
+ * is obtained from an HTTP Post to the url provided by getCertificateRequest.
+ * <p>
+ * The public X509 certificate chain and wrapped private key are returned
+ * in the returned Certificate objec. The certificate chain is in PEM format.
+ * The wrapped private key should be stored in application private
+ * storage, and used when invoking the signRSA method.
+ *
+ * @param response the opaque certificate response byte array to provide to the
+ * DRM engine plugin.
+ *
+ * @throws DeniedByServerException if the response indicates that the
+ * server rejected the request
+ *
+ * @hide - not part of the public API at this time
+ */
+ public Certificate provideCertificateResponse(byte[] response)
+ throws DeniedByServerException {
+ return provideProvisionResponseNative(response);
+ }
+
+ private static final native byte[] signRSANative(MediaDrm drm, byte[] sessionId,
+ String algorithm, byte[] wrappedKey,
+ byte[] message);
+
+ /**
+ * Sign data using an RSA key
+ *
+ * @param context the app context
+ * @param sessionId a sessionId obtained from openSession on the MediaDrm object
+ * @param algorithm the signing algorithm to use, e.g. "PKCS1-BlockType1"
+ * @param wrappedKey - the wrapped (encrypted) RSA private key obtained
+ * from provideCertificateResponse
+ * @param message the data for which a signature is to be computed
+ *
+ * @hide - not part of the public API at this time
+ */
+ public byte[] signRSA(Context context, byte[] sessionId, String algorithm, byte[] wrappedKey, byte[] message) {
+ return signRSANative(this, sessionId, algorithm, wrappedKey, message);
+ }
+
@Override
protected void finalize() {
native_finalize();
diff --git a/media/java/android/media/MediaFocusControl.java b/media/java/android/media/MediaFocusControl.java
index 1016dd4..f688d81 100644
--- a/media/java/android/media/MediaFocusControl.java
+++ b/media/java/android/media/MediaFocusControl.java
@@ -32,6 +32,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
+import android.media.PlayerRecord.RemotePlaybackState;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -73,8 +74,7 @@
private boolean mIsRinging = false;
private final PowerManager.WakeLock mMediaEventWakeLock;
- //FIXME should be private
- protected final MediaEventHandler mEventHandler;
+ private final MediaEventHandler mEventHandler;
private final Context mContext;
private final ContentResolver mContentResolver;
private final VolumeController mVolumeController;
@@ -120,6 +120,9 @@
mHasRemotePlayback = false;
mMainRemoteIsActive = false;
+
+ PlayerRecord.setMediaFocusControl(this);
+
postReevaluateRemote();
}
@@ -251,7 +254,7 @@
currentUser);
if (DEBUG_RC) { Log.d(TAG, " > enabled list: " + enabledNotifListeners); }
synchronized(mAudioFocusLock) {
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
// check whether the "enable" status of each RCD with a notification listener
// has changed
final String[] enabledComponents;
@@ -330,6 +333,7 @@
private static final int MSG_RCC_UPDATE_METADATA = 9;
private static final int MSG_RCDISPLAY_INIT_INFO = 10;
private static final int MSG_REEVALUATE_RCD = 11;
+ private static final int MSG_UNREGISTER_MEDIABUTTONINTENT = 12;
// sendMsg() flags
/** If the msg is already queued, replace it with this one. */
@@ -351,8 +355,7 @@
handler.sendMessageDelayed(handler.obtainMessage(msg, arg1, arg2, obj), delay);
}
- //FIXME should be private
- protected class MediaEventHandler extends Handler {
+ private class MediaEventHandler extends Handler {
MediaEventHandler(Looper looper) {
super(looper);
}
@@ -370,7 +373,7 @@
case MSG_RCDISPLAY_UPDATE:
// msg.obj is guaranteed to be non null
- onRcDisplayUpdate( (MediaController) msg.obj, msg.arg1);
+ onRcDisplayUpdate( (PlayerRecord) msg.obj, msg.arg1);
break;
case MSG_REEVALUATE_REMOTE:
@@ -390,7 +393,7 @@
case MSG_RCC_NEW_PLAYBACK_STATE:
onNewPlaybackStateForRcc(msg.arg1 /* rccId */,
msg.arg2 /* state */,
- (MediaController.RccPlaybackState)msg.obj /* newState */);
+ (PlayerRecord.RccPlaybackState)msg.obj /* newState */);
break;
case MSG_RCC_SEEK_REQUEST:
@@ -416,6 +419,10 @@
case MSG_REEVALUATE_RCD:
onReevaluateRemoteControlDisplays();
break;
+
+ case MSG_UNREGISTER_MEDIABUTTONINTENT:
+ unregisterMediaButtonIntent( (PendingIntent) msg.obj );
+ break;
}
}
}
@@ -465,7 +472,7 @@
exFocusOwner.handleFocusLoss(AudioManager.AUDIOFOCUS_LOSS);
exFocusOwner.release();
// clear RCD
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
clearRemoteControlDisplay_syncAfRcs();
}
}
@@ -529,7 +536,7 @@
// notify the new top of the stack it gained focus
notifyTopOfAudioFocusStack();
// there's a new top of the stack, let the remote control know
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
}
}
@@ -576,7 +583,7 @@
// notify the new top of the stack it gained focus.
notifyTopOfAudioFocusStack();
// there's a new top of the stack, let the remote control know
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
}
}
@@ -688,7 +695,7 @@
clientId, afdh, callingPackageName, Binder.getCallingUid()));
// there's a new top of the stack, let the remote control know
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
}
}//synchronized(mAudioFocusLock)
@@ -752,7 +759,7 @@
}
// event filtering for telephony
synchronized(mRingingLock) {
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
if ((mMediaReceiverForCalls != null) &&
(mIsRinging || (mAudioService.getMode() == AudioSystem.MODE_IN_CALL))) {
dispatchMediaKeyEventForCalls(keyEvent, needWakeLock);
@@ -805,15 +812,15 @@
}
Intent keyIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
keyIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
- synchronized(mMCStack) {
- if (!mMCStack.empty()) {
+ synchronized(mPRStack) {
+ if (!mPRStack.empty()) {
// send the intent that was registered by the client
try {
- mMCStack.peek().mMediaIntent.send(mContext,
+ mPRStack.peek().getMediaButtonIntent().send(mContext,
needWakeLock ? WAKELOCK_RELEASE_ON_FINISHED : 0 /*code*/,
keyIntent, this, mEventHandler);
} catch (CanceledException e) {
- Log.e(TAG, "Error sending pending intent " + mMCStack.peek());
+ Log.e(TAG, "Error sending pending intent " + mPRStack.peek());
e.printStackTrace();
}
} else {
@@ -1023,7 +1030,7 @@
};
/**
- * Synchronization on mCurrentRcLock always inside a block synchronized on mMCStack
+ * Synchronization on mCurrentRcLock always inside a block synchronized on mPRStack
*/
private final Object mCurrentRcLock = new Object();
/**
@@ -1052,47 +1059,6 @@
*/
private int mCurrentRcClientGen = 0;
- /**
- * Inner class to monitor remote control client deaths, and remove the client for the
- * remote control stack if necessary.
- */
- protected class RcClientDeathHandler implements IBinder.DeathRecipient {
- //FIXME should be private
- final protected IBinder mCb; // To be notified of client's death
- final private PendingIntent mMediaIntent;
-
- RcClientDeathHandler(IBinder cb, PendingIntent pi) {
- mCb = cb;
- mMediaIntent = pi;
- }
-
- public void binderDied() {
- Log.w(TAG, " RemoteControlClient died");
- // remote control client died, make sure the displays don't use it anymore
- // by setting its remote control client to null
- registerRemoteControlClient(mMediaIntent, null/*rcClient*/, null/*ignored*/);
- // the dead client was maybe handling remote playback, reevaluate
- postReevaluateRemote();
- }
-
- public IBinder getBinder() {
- return mCb;
- }
- }
-
- protected class RemotePlaybackState {
- int mRccId;
- int mVolume;
- int mVolumeMax;
- int mVolumeHandling;
-
- private RemotePlaybackState(int id, int vol, int volMax) {
- mRccId = id;
- mVolume = vol;
- mVolumeMax = volMax;
- mVolumeHandling = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME_HANDLING;
- }
- }
/**
* Internal cache for the playback information of the RemoteControlClient whose volume gets to
@@ -1116,10 +1082,10 @@
/**
* The stack of remote control event receivers.
* Code sections and methods that modify the remote control event receiver stack are
- * synchronized on mMCStack, but also BEFORE on mFocusLock as any change in either
+ * synchronized on mPRStack, but also BEFORE on mFocusLock as any change in either
* stack, audio focus or RC, can lead to a change in the remote control display
*/
- private final Stack<MediaController> mMCStack = new Stack<MediaController>();
+ private final Stack<PlayerRecord> mPRStack = new Stack<PlayerRecord>();
/**
* The component the telephony package can register so telephony calls have priority to
@@ -1133,17 +1099,10 @@
*/
private void dumpRCStack(PrintWriter pw) {
pw.println("\nRemote Control stack entries (last is top of stack):");
- synchronized(mMCStack) {
- Iterator<MediaController> stackIterator = mMCStack.iterator();
+ synchronized(mPRStack) {
+ Iterator<PlayerRecord> stackIterator = mPRStack.iterator();
while(stackIterator.hasNext()) {
- MediaController mcse = stackIterator.next();
- pw.println(" pi: " + mcse.mMediaIntent +
- " -- pack: " + mcse.mCallingPackageName +
- " -- ercvr: " + mcse.mReceiverComponent +
- " -- client: " + mcse.mRcClient +
- " -- uid: " + mcse.mCallingUid +
- " -- type: " + mcse.mPlaybackType +
- " state: " + mcse.mPlaybackState);
+ stackIterator.next().dump(pw, true);
}
}
}
@@ -1155,18 +1114,10 @@
*/
private void dumpRCCStack(PrintWriter pw) {
pw.println("\nRemote Control Client stack entries (last is top of stack):");
- synchronized(mMCStack) {
- Iterator<MediaController> stackIterator = mMCStack.iterator();
+ synchronized(mPRStack) {
+ Iterator<PlayerRecord> stackIterator = mPRStack.iterator();
while(stackIterator.hasNext()) {
- MediaController mcse = stackIterator.next();
- pw.println(" uid: " + mcse.mCallingUid +
- " -- id: " + mcse.mRccId +
- " -- type: " + mcse.mPlaybackType +
- " -- state: " + mcse.mPlaybackState +
- " -- vol handling: " + mcse.mPlaybackVolumeHandling +
- " -- vol: " + mcse.mPlaybackVolume +
- " -- volMax: " + mcse.mPlaybackVolumeMax +
- " -- volObs: " + mcse.mRemoteVolumeObs);
+ stackIterator.next().dump(pw, false);
}
synchronized(mCurrentRcLock) {
pw.println("\nCurrent remote control generation ID = " + mCurrentRcClientGen);
@@ -1191,7 +1142,7 @@
*/
private void dumpRCDList(PrintWriter pw) {
pw.println("\nRemote Control Display list entries:");
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
final Iterator<DisplayInfoForServer> displayIterator = mRcDisplays.iterator();
while (displayIterator.hasNext()) {
final DisplayInfoForServer di = displayIterator.next();
@@ -1210,47 +1161,49 @@
* Pre-condition: packageName != null
*/
private void cleanupMediaButtonReceiverForPackage(String packageName, boolean removeAll) {
- synchronized(mMCStack) {
- if (mMCStack.empty()) {
+ synchronized(mPRStack) {
+ if (mPRStack.empty()) {
return;
} else {
final PackageManager pm = mContext.getPackageManager();
- MediaController oldTop = mMCStack.peek();
- Iterator<MediaController> stackIterator = mMCStack.iterator();
+ PlayerRecord oldTop = mPRStack.peek();
+ Iterator<PlayerRecord> stackIterator = mPRStack.iterator();
// iterate over the stack entries
// (using an iterator on the stack so we can safely remove an entry after having
// evaluated it, traversal order doesn't matter here)
while(stackIterator.hasNext()) {
- MediaController mcse = stackIterator.next();
- if (removeAll && packageName.equals(mcse.mMediaIntent.getCreatorPackage())) {
+ PlayerRecord prse = stackIterator.next();
+ if (removeAll
+ && packageName.equals(prse.getMediaButtonIntent().getCreatorPackage()))
+ {
// a stack entry is from the package being removed, remove it from the stack
stackIterator.remove();
- mcse.destroy();
- } else if (mcse.mReceiverComponent != null) {
+ prse.destroy();
+ } else if (prse.getMediaButtonReceiver() != null) {
try {
// Check to see if this receiver still exists.
- pm.getReceiverInfo(mcse.mReceiverComponent, 0);
+ pm.getReceiverInfo(prse.getMediaButtonReceiver(), 0);
} catch (PackageManager.NameNotFoundException e) {
// Not found -- remove it!
stackIterator.remove();
- mcse.destroy();
+ prse.destroy();
}
}
}
- if (mMCStack.empty()) {
+ if (mPRStack.empty()) {
// no saved media button receiver
mEventHandler.sendMessage(
mEventHandler.obtainMessage(MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0,
null));
- } else if (oldTop != mMCStack.peek()) {
+ } else if (oldTop != mPRStack.peek()) {
// the top of the stack has changed, save it in the system settings
// by posting a message to persist it; only do this however if it has
// a concrete component name (is not a transient registration)
- MediaController mcse = mMCStack.peek();
- if (mcse.mReceiverComponent != null) {
+ PlayerRecord prse = mPRStack.peek();
+ if (prse.getMediaButtonReceiver() != null) {
mEventHandler.sendMessage(
mEventHandler.obtainMessage(MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0,
- mcse.mReceiverComponent));
+ prse.getMediaButtonReceiver()));
}
}
}
@@ -1284,28 +1237,28 @@
/**
* Helper function:
* Set the new remote control receiver at the top of the RC focus stack.
- * Called synchronized on mAudioFocusLock, then mMCStack
+ * Called synchronized on mAudioFocusLock, then mPRStack
* precondition: mediaIntent != null
- * @return true if mMCStack was changed, false otherwise
+ * @return true if mPRStack was changed, false otherwise
*/
private boolean pushMediaButtonReceiver_syncAfRcs(PendingIntent mediaIntent,
ComponentName target, IBinder token) {
// already at top of stack?
- if (!mMCStack.empty() && mMCStack.peek().mMediaIntent.equals(mediaIntent)) {
+ if (!mPRStack.empty() && mPRStack.peek().hasMatchingMediaButtonIntent(mediaIntent)) {
return false;
}
if (mAppOps.noteOp(AppOpsManager.OP_TAKE_MEDIA_BUTTONS, Binder.getCallingUid(),
mediaIntent.getCreatorPackage()) != AppOpsManager.MODE_ALLOWED) {
return false;
}
- MediaController mcse = null;
+ PlayerRecord prse = null;
boolean wasInsideStack = false;
try {
- for (int index = mMCStack.size()-1; index >= 0; index--) {
- mcse = mMCStack.elementAt(index);
- if(mcse.mMediaIntent.equals(mediaIntent)) {
+ for (int index = mPRStack.size()-1; index >= 0; index--) {
+ prse = mPRStack.elementAt(index);
+ if(prse.hasMatchingMediaButtonIntent(mediaIntent)) {
// ok to remove element while traversing the stack since we're leaving the loop
- mMCStack.removeElementAt(index);
+ mPRStack.removeElementAt(index);
wasInsideStack = true;
break;
}
@@ -1315,9 +1268,9 @@
Log.e(TAG, "Wrong index accessing media button stack, lock error? ", e);
}
if (!wasInsideStack) {
- mcse = new MediaController(this, mediaIntent, target, token);
+ prse = new PlayerRecord(mediaIntent, target, token);
}
- mMCStack.push(mcse); // mcse is never null
+ mPRStack.push(prse); // prse is never null
// post message to persist the default media button receiver
if (target != null) {
@@ -1332,17 +1285,17 @@
/**
* Helper function:
* Remove the remote control receiver from the RC focus stack.
- * Called synchronized on mAudioFocusLock, then mMCStack
+ * Called synchronized on mAudioFocusLock, then mPRStack
* precondition: pi != null
*/
private void removeMediaButtonReceiver_syncAfRcs(PendingIntent pi) {
try {
- for (int index = mMCStack.size()-1; index >= 0; index--) {
- final MediaController mcse = mMCStack.elementAt(index);
- if (mcse.mMediaIntent.equals(pi)) {
- mcse.destroy();
+ for (int index = mPRStack.size()-1; index >= 0; index--) {
+ final PlayerRecord prse = mPRStack.elementAt(index);
+ if (prse.hasMatchingMediaButtonIntent(pi)) {
+ prse.destroy();
// ok to remove element while traversing the stack since we're leaving the loop
- mMCStack.removeElementAt(index);
+ mPRStack.removeElementAt(index);
break;
}
}
@@ -1354,10 +1307,10 @@
/**
* Helper function:
- * Called synchronized on mMCStack
+ * Called synchronized on mPRStack
*/
private boolean isCurrentRcController(PendingIntent pi) {
- if (!mMCStack.empty() && mMCStack.peek().mMediaIntent.equals(pi)) {
+ if (!mPRStack.empty() && mPRStack.peek().hasMatchingMediaButtonIntent(pi)) {
return true;
}
return false;
@@ -1378,7 +1331,7 @@
*/
private void setNewRcClientOnDisplays_syncRcsCurrc(int newClientGeneration,
PendingIntent newMediaIntent, boolean clearing) {
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
if (mRcDisplays.size() > 0) {
final Iterator<DisplayInfoForServer> displayIterator = mRcDisplays.iterator();
while (displayIterator.hasNext()) {
@@ -1402,12 +1355,12 @@
private void setNewRcClientGenerationOnClients_syncRcsCurrc(int newClientGeneration) {
// (using an iterator on the stack so we can safely remove an entry if needed,
// traversal order doesn't matter here as we update all entries)
- Iterator<MediaController> stackIterator = mMCStack.iterator();
+ Iterator<PlayerRecord> stackIterator = mPRStack.iterator();
while(stackIterator.hasNext()) {
- MediaController se = stackIterator.next();
- if ((se != null) && (se.mRcClient != null)) {
+ PlayerRecord se = stackIterator.next();
+ if ((se != null) && (se.getRcc() != null)) {
try {
- se.mRcClient.setCurrentClientGenerationId(newClientGeneration);
+ se.getRcc().setCurrentClientGenerationId(newClientGeneration);
} catch (RemoteException e) {
Log.w(TAG, "Dead client in setNewRcClientGenerationOnClients_syncRcsCurrc()",e);
stackIterator.remove();
@@ -1439,7 +1392,7 @@
private void onRcDisplayClear() {
if (DEBUG_RC) Log.i(TAG, "Clear remote control display");
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
synchronized(mCurrentRcLock) {
mCurrentRcClientGen++;
// synchronously update the displays and clients with the new client generation
@@ -1452,17 +1405,17 @@
/**
* Called when processing MSG_RCDISPLAY_UPDATE event
*/
- private void onRcDisplayUpdate(MediaController mcse, int flags /* USED ?*/) {
- synchronized(mMCStack) {
+ private void onRcDisplayUpdate(PlayerRecord prse, int flags /* USED ?*/) {
+ synchronized(mPRStack) {
synchronized(mCurrentRcLock) {
- if ((mCurrentRcClient != null) && (mCurrentRcClient.equals(mcse.mRcClient))) {
+ if ((mCurrentRcClient != null) && (mCurrentRcClient.equals(prse.getRcc()))) {
if (DEBUG_RC) Log.i(TAG, "Display/update remote control ");
mCurrentRcClientGen++;
// synchronously update the displays and clients with
// the new client generation
setNewRcClient_syncRcsCurrc(mCurrentRcClientGen,
- mcse.mMediaIntent /*newMediaIntent*/,
+ prse.getMediaButtonIntent() /*newMediaIntent*/,
false /*clearing*/);
// tell the current client that it needs to send info
@@ -1488,7 +1441,7 @@
* a single RemoteControlDisplay, NOT all of them, as with MSG_RCDISPLAY_UPDATE.
*/
private void onRcDisplayInitInfo(IRemoteControlDisplay newRcd, int w, int h) {
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
synchronized(mCurrentRcLock) {
if (mCurrentRcClient != null) {
if (DEBUG_RC) { Log.i(TAG, "Init RCD with current info"); }
@@ -1515,7 +1468,7 @@
/**
* Helper function:
- * Called synchronized on mMCStack
+ * Called synchronized on mPRStack
*/
private void clearRemoteControlDisplay_syncAfRcs() {
synchronized(mCurrentRcLock) {
@@ -1530,35 +1483,35 @@
* checkUpdateRemoteControlDisplay_syncAfRcs() which checks the preconditions for
* this method.
* Preconditions:
- * - called synchronized mAudioFocusLock then on mMCStack
- * - mMCStack.isEmpty() is false
+ * - called synchronized mAudioFocusLock then on mPRStack
+ * - mPRStack.isEmpty() is false
*/
private void updateRemoteControlDisplay_syncAfRcs(int infoChangedFlags) {
- MediaController mcse = mMCStack.peek();
+ PlayerRecord prse = mPRStack.peek();
int infoFlagsAboutToBeUsed = infoChangedFlags;
// this is where we enforce opt-in for information display on the remote controls
// with the new AudioManager.registerRemoteControlClient() API
- if (mcse.mRcClient == null) {
+ if (prse.getRcc() == null) {
//Log.w(TAG, "Can't update remote control display with null remote control client");
clearRemoteControlDisplay_syncAfRcs();
return;
}
synchronized(mCurrentRcLock) {
- if (!mcse.mRcClient.equals(mCurrentRcClient)) {
+ if (!prse.getRcc().equals(mCurrentRcClient)) {
// new RC client, assume every type of information shall be queried
infoFlagsAboutToBeUsed = RC_INFO_ALL;
}
- mCurrentRcClient = mcse.mRcClient;
- mCurrentRcClientIntent = mcse.mMediaIntent;
+ mCurrentRcClient = prse.getRcc();
+ mCurrentRcClientIntent = prse.getMediaButtonIntent();
}
// will cause onRcDisplayUpdate() to be called in AudioService's handler thread
mEventHandler.sendMessage( mEventHandler.obtainMessage(MSG_RCDISPLAY_UPDATE,
- infoFlagsAboutToBeUsed /* arg1 */, 0, mcse /* obj, != null */) );
+ infoFlagsAboutToBeUsed /* arg1 */, 0, prse /* obj, != null */) );
}
/**
* Helper function:
- * Called synchronized on mAudioFocusLock, then mMCStack
+ * Called synchronized on mAudioFocusLock, then mPRStack
* Check whether the remote control display should be updated, triggers the update if required
* @param infoChangedFlags the flags corresponding to the remote control client information
* that has changed, if applicable (checking for the update conditions might trigger a
@@ -1567,7 +1520,7 @@
private void checkUpdateRemoteControlDisplay_syncAfRcs(int infoChangedFlags) {
// determine whether the remote control display should be refreshed
// if either stack is empty, there is a mismatch, so clear the RC display
- if (mMCStack.isEmpty() || mFocusStack.isEmpty()) {
+ if (mPRStack.isEmpty() || mFocusStack.isEmpty()) {
clearRemoteControlDisplay_syncAfRcs();
return;
}
@@ -1600,19 +1553,19 @@
}
// if the audio focus and RC owners belong to different packages, there is a mismatch, clear
- if (!af.hasSamePackage(mMCStack.peek().mCallingPackageName)) {
+ if (!af.hasSamePackage(mPRStack.peek().getCallingPackageName())) {
clearRemoteControlDisplay_syncAfRcs();
return;
}
// if the audio focus didn't originate from the same Uid as the one in which the remote
// control information will be retrieved, clear
- if (!af.hasSameUid(mMCStack.peek().mCallingUid)) {
+ if (!af.hasSameUid(mPRStack.peek().getCallingUid())) {
clearRemoteControlDisplay_syncAfRcs();
return;
}
// refresh conditions were verified: update the remote controls
- // ok to call: synchronized mAudioFocusLock then on mMCStack, mMCStack is not empty
+ // ok to call: synchronized mAudioFocusLock then on mPRStack, mPRStack is not empty
updateRemoteControlDisplay_syncAfRcs(infoChangedFlags);
}
@@ -1630,25 +1583,25 @@
private void onPromoteRcc(int rccId) {
if (DEBUG_RC) { Log.d(TAG, "Promoting RCC " + rccId); }
synchronized(mAudioFocusLock) {
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
// ignore if given RCC ID is already at top of remote control stack
- if (!mMCStack.isEmpty() && (mMCStack.peek().mRccId == rccId)) {
+ if (!mPRStack.isEmpty() && (mPRStack.peek().getRccId() == rccId)) {
return;
}
int indexToPromote = -1;
try {
- for (int index = mMCStack.size()-1; index >= 0; index--) {
- final MediaController mcse = mMCStack.elementAt(index);
- if (mcse.mRccId == rccId) {
+ for (int index = mPRStack.size()-1; index >= 0; index--) {
+ final PlayerRecord prse = mPRStack.elementAt(index);
+ if (prse.getRccId() == rccId) {
indexToPromote = index;
break;
}
}
if (indexToPromote >= 0) {
if (DEBUG_RC) { Log.d(TAG, " moving RCC from index " + indexToPromote
- + " to " + (mMCStack.size()-1)); }
- final MediaController mcse = mMCStack.remove(indexToPromote);
- mMCStack.push(mcse);
+ + " to " + (mPRStack.size()-1)); }
+ final PlayerRecord prse = mPRStack.remove(indexToPromote);
+ mPRStack.push(prse);
// the RC stack changed, reevaluate the display
checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
}
@@ -1656,7 +1609,7 @@
// not expected to happen, indicates improper concurrent modification
Log.e(TAG, "Wrong index accessing RC stack, lock error? ", e);
}
- }//synchronized(mMCStack)
+ }//synchronized(mPRStack)
}//synchronized(mAudioFocusLock)
}
@@ -1669,7 +1622,7 @@
Log.i(TAG, " Remote Control registerMediaButtonIntent() for " + mediaIntent);
synchronized(mAudioFocusLock) {
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
if (pushMediaButtonReceiver_syncAfRcs(mediaIntent, eventReceiver, token)) {
// new RC client, assume every type of information shall be queried
checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
@@ -1687,7 +1640,7 @@
Log.i(TAG, " Remote Control unregisterMediaButtonIntent() for " + mediaIntent);
synchronized(mAudioFocusLock) {
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
boolean topOfStackWillChange = isCurrentRcController(mediaIntent);
removeMediaButtonReceiver_syncAfRcs(mediaIntent);
if (topOfStackWillChange) {
@@ -1698,6 +1651,12 @@
}
}
+ protected void unregisterMediaButtonIntentAsync(final PendingIntent mediaIntent) {
+ mEventHandler.sendMessage(
+ mEventHandler.obtainMessage(MSG_UNREGISTER_MEDIABUTTONINTENT, 0, 0,
+ mediaIntent));
+ }
+
/**
* see AudioManager.registerMediaButtonEventReceiverForCalls(ComponentName c)
* precondition: c != null
@@ -1708,7 +1667,7 @@
Log.e(TAG, "Invalid permissions to register media button receiver for calls");
return;
}
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
mMediaReceiverForCalls = c;
}
}
@@ -1722,14 +1681,14 @@
Log.e(TAG, "Invalid permissions to unregister media button receiver for calls");
return;
}
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
mMediaReceiverForCalls = null;
}
}
/**
* see AudioManager.registerRemoteControlClient(ComponentName eventReceiver, ...)
- * @return the unique ID of the MediaController associated with the RemoteControlClient
+ * @return the unique ID of the PlayerRecord associated with the RemoteControlClient
* Note: using this method with rcClient == null is a way to "disable" the IRemoteControlClient
* without modifying the RC stack, but while still causing the display to refresh (will
* become blank as a result of this)
@@ -1739,45 +1698,26 @@
if (DEBUG_RC) Log.i(TAG, "Register remote control client rcClient="+rcClient);
int rccId = RemoteControlClient.RCSE_ID_UNREGISTERED;
synchronized(mAudioFocusLock) {
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
// store the new display information
try {
- for (int index = mMCStack.size()-1; index >= 0; index--) {
- final MediaController mcse = mMCStack.elementAt(index);
- if(mcse.mMediaIntent.equals(mediaIntent)) {
- // already had a remote control client?
- if (mcse.mRcClientDeathHandler != null) {
- // stop monitoring the old client's death
- mcse.unlinkToRcClientDeath();
- }
- // save the new remote control client
- mcse.mRcClient = rcClient;
- mcse.mCallingPackageName = callingPackageName;
- mcse.mCallingUid = Binder.getCallingUid();
+ for (int index = mPRStack.size()-1; index >= 0; index--) {
+ final PlayerRecord prse = mPRStack.elementAt(index);
+ if(prse.hasMatchingMediaButtonIntent(mediaIntent)) {
+ prse.resetControllerInfoForRcc(rcClient, callingPackageName,
+ Binder.getCallingUid());
+
if (rcClient == null) {
- // here mcse.mRcClientDeathHandler is null;
- mcse.resetPlaybackInfo();
break;
}
- rccId = mcse.mRccId;
+
+ rccId = prse.getRccId();
// there is a new (non-null) client:
- // 1/ give the new client the displays (if any)
+ // give the new client the displays (if any)
if (mRcDisplays.size() > 0) {
- plugRemoteControlDisplaysIntoClient_syncRcStack(mcse.mRcClient);
+ plugRemoteControlDisplaysIntoClient_syncRcStack(prse.getRcc());
}
- // 2/ monitor the new client's death
- IBinder b = mcse.mRcClient.asBinder();
- RcClientDeathHandler rcdh =
- new RcClientDeathHandler(b, mcse.mMediaIntent);
- try {
- b.linkToDeath(rcdh, 0);
- } catch (RemoteException e) {
- // remote control client is DOA, disqualify it
- Log.w(TAG, "registerRemoteControlClient() has a dead client " + b);
- mcse.mRcClient = null;
- }
- mcse.mRcClientDeathHandler = rcdh;
break;
}
}//for
@@ -1791,7 +1731,7 @@
if (isCurrentRcController(mediaIntent)) {
checkUpdateRemoteControlDisplay_syncAfRcs(RC_INFO_ALL);
}
- }//synchronized(mMCStack)
+ }//synchronized(mPRStack)
}//synchronized(mAudioFocusLock)
return rccId;
}
@@ -1804,20 +1744,16 @@
IRemoteControlClient rcClient) {
if (DEBUG_RC) Log.i(TAG, "Unregister remote control client rcClient="+rcClient);
synchronized(mAudioFocusLock) {
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
boolean topRccChange = false;
try {
- for (int index = mMCStack.size()-1; index >= 0; index--) {
- final MediaController mcse = mMCStack.elementAt(index);
- if ((mcse.mMediaIntent.equals(mediaIntent))
- && rcClient.equals(mcse.mRcClient)) {
+ for (int index = mPRStack.size()-1; index >= 0; index--) {
+ final PlayerRecord prse = mPRStack.elementAt(index);
+ if ((prse.hasMatchingMediaButtonIntent(mediaIntent))
+ && rcClient.equals(prse.getRcc())) {
// we found the IRemoteControlClient to unregister
- // stop monitoring its death
- mcse.unlinkToRcClientDeath();
- // reset the client-related fields
- mcse.mRcClient = null;
- mcse.mCallingPackageName = null;
- topRccChange = (index == mMCStack.size()-1);
+ prse.resetControllerInfoForNoRcc();
+ topRccChange = (index == mPRStack.size()-1);
// there can only be one matching RCC in the RC stack, we're done
break;
}
@@ -1881,7 +1817,7 @@
}
public void binderDied() {
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
Log.w(TAG, "RemoteControl: display " + mRcDisplay + " died");
// remove the display from the list
final Iterator<DisplayInfoForServer> displayIterator = mRcDisplays.iterator();
@@ -1899,7 +1835,7 @@
/**
* The remote control displays.
- * Access synchronized on mMCStack
+ * Access synchronized on mPRStack
*/
private ArrayList<DisplayInfoForServer> mRcDisplays = new ArrayList<DisplayInfoForServer>(1);
@@ -1927,12 +1863,12 @@
boolean enabled) {
// let all the remote control clients know whether the given display is enabled
// (so the remote control stack traversal order doesn't matter).
- final Iterator<MediaController> stackIterator = mMCStack.iterator();
+ final Iterator<PlayerRecord> stackIterator = mPRStack.iterator();
while(stackIterator.hasNext()) {
- MediaController mcse = stackIterator.next();
- if(mcse.mRcClient != null) {
+ PlayerRecord prse = stackIterator.next();
+ if(prse.getRcc() != null) {
try {
- mcse.mRcClient.enableRemoteControlDisplay(rcd, enabled);
+ prse.getRcc().enableRemoteControlDisplay(rcd, enabled);
} catch (RemoteException e) {
Log.e(TAG, "Error connecting RCD to client: ", e);
}
@@ -1973,7 +1909,7 @@
ComponentName listenerComp) {
if (DEBUG_RC) Log.d(TAG, ">>> registerRemoteControlDisplay("+rcd+")");
synchronized(mAudioFocusLock) {
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
if ((rcd == null) || rcDisplayIsPluggedIn_syncRcStack(rcd)) {
return;
}
@@ -1989,12 +1925,12 @@
// let all the remote control clients know there is a new display (so the remote
// control stack traversal order doesn't matter).
- Iterator<MediaController> stackIterator = mMCStack.iterator();
+ Iterator<PlayerRecord> stackIterator = mPRStack.iterator();
while(stackIterator.hasNext()) {
- MediaController mcse = stackIterator.next();
- if(mcse.mRcClient != null) {
+ PlayerRecord prse = stackIterator.next();
+ if(prse.getRcc() != null) {
try {
- mcse.mRcClient.plugRemoteControlDisplay(rcd, w, h);
+ prse.getRcc().plugRemoteControlDisplay(rcd, w, h);
} catch (RemoteException e) {
Log.e(TAG, "Error connecting RCD to client: ", e);
}
@@ -2019,7 +1955,7 @@
*/
protected void unregisterRemoteControlDisplay(IRemoteControlDisplay rcd) {
if (DEBUG_RC) Log.d(TAG, "<<< unregisterRemoteControlDisplay("+rcd+")");
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
if (rcd == null) {
return;
}
@@ -2038,12 +1974,12 @@
if (displayWasPluggedIn) {
// disconnect this remote control display from all the clients, so the remote
// control stack traversal order doesn't matter
- final Iterator<MediaController> stackIterator = mMCStack.iterator();
+ final Iterator<PlayerRecord> stackIterator = mPRStack.iterator();
while(stackIterator.hasNext()) {
- final MediaController mcse = stackIterator.next();
- if(mcse.mRcClient != null) {
+ final PlayerRecord prse = stackIterator.next();
+ if(prse.getRcc() != null) {
try {
- mcse.mRcClient.unplugRemoteControlDisplay(rcd);
+ prse.getRcc().unplugRemoteControlDisplay(rcd);
} catch (RemoteException e) {
Log.e(TAG, "Error disconnecting remote control display to client: ", e);
}
@@ -2065,7 +2001,7 @@
* display doesn't need to receive artwork.
*/
protected void remoteControlDisplayUsesBitmapSize(IRemoteControlDisplay rcd, int w, int h) {
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
final Iterator<DisplayInfoForServer> displayIterator = mRcDisplays.iterator();
boolean artworkSizeUpdate = false;
while (displayIterator.hasNext() && !artworkSizeUpdate) {
@@ -2081,12 +2017,12 @@
if (artworkSizeUpdate) {
// RCD is currently plugged in and its artwork size has changed, notify all RCCs,
// stack traversal order doesn't matter
- final Iterator<MediaController> stackIterator = mMCStack.iterator();
+ final Iterator<PlayerRecord> stackIterator = mPRStack.iterator();
while(stackIterator.hasNext()) {
- final MediaController mcse = stackIterator.next();
- if(mcse.mRcClient != null) {
+ final PlayerRecord prse = stackIterator.next();
+ if(prse.getRcc() != null) {
try {
- mcse.mRcClient.setBitmapSizeForDisplay(rcd, w, h);
+ prse.getRcc().setBitmapSizeForDisplay(rcd, w, h);
} catch (RemoteException e) {
Log.e(TAG, "Error setting bitmap size for RCD on RCC: ", e);
}
@@ -2110,7 +2046,7 @@
*/
protected void remoteControlDisplayWantsPlaybackPositionSync(IRemoteControlDisplay rcd,
boolean wantsSync) {
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
boolean rcdRegistered = false;
// store the information about this display
// (display stack traversal order doesn't matter).
@@ -2128,12 +2064,12 @@
}
// notify all current RemoteControlClients
// (stack traversal order doesn't matter as we notify all RCCs)
- final Iterator<MediaController> stackIterator = mMCStack.iterator();
+ final Iterator<PlayerRecord> stackIterator = mPRStack.iterator();
while (stackIterator.hasNext()) {
- final MediaController mcse = stackIterator.next();
- if (mcse.mRcClient != null) {
+ final PlayerRecord prse = stackIterator.next();
+ if (prse.getRcc() != null) {
try {
- mcse.mRcClient.setWantsSyncForDisplay(rcd, wantsSync);
+ prse.getRcc().setWantsSyncForDisplay(rcd, wantsSync);
} catch (RemoteException e) {
Log.e(TAG, "Error setting position sync flag for RCD on RCC: ", e);
}
@@ -2144,7 +2080,7 @@
protected void setRemoteControlClientPlaybackPosition(int generationId, long timeMs) {
// ignore position change requests if invalid generation ID
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
synchronized(mCurrentRcLock) {
if (mCurrentRcClientGen != generationId) {
return;
@@ -2159,7 +2095,7 @@
private void onSetRemoteControlClientPlaybackPosition(int generationId, long timeMs) {
if(DEBUG_RC) Log.d(TAG, "onSetRemoteControlClientPlaybackPosition(genId=" + generationId +
", timeMs=" + timeMs + ")");
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
synchronized(mCurrentRcLock) {
if ((mCurrentRcClient != null) && (mCurrentRcClientGen == generationId)) {
// tell the current client to seek to the requested location
@@ -2182,7 +2118,7 @@
private void onUpdateRemoteControlClientMetadata(int genId, int key, Rating value) {
if(DEBUG_RC) Log.d(TAG, "onUpdateRemoteControlClientMetadata(genId=" + genId +
", what=" + key + ",rating=" + value + ")");
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
synchronized(mCurrentRcLock) {
if ((mCurrentRcClient != null) && (mCurrentRcClientGen == genId)) {
try {
@@ -2213,20 +2149,20 @@
private void onNewPlaybackInfoForRcc(int rccId, int key, int value) {
if(DEBUG_RC) Log.d(TAG, "onNewPlaybackInfoForRcc(id=" + rccId +
", what=" + key + ",val=" + value + ")");
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
// iterating from top of stack as playback information changes are more likely
// on entries at the top of the remote control stack
try {
- for (int index = mMCStack.size()-1; index >= 0; index--) {
- final MediaController mcse = mMCStack.elementAt(index);
- if (mcse.mRccId == rccId) {
+ for (int index = mPRStack.size()-1; index >= 0; index--) {
+ final PlayerRecord prse = mPRStack.elementAt(index);
+ if (prse.getRccId() == rccId) {
switch (key) {
case RemoteControlClient.PLAYBACKINFO_PLAYBACK_TYPE:
- mcse.mPlaybackType = value;
+ prse.mPlaybackType = value;
postReevaluateRemote();
break;
case RemoteControlClient.PLAYBACKINFO_VOLUME:
- mcse.mPlaybackVolume = value;
+ prse.mPlaybackVolume = value;
synchronized (mMainRemote) {
if (rccId == mMainRemote.mRccId) {
mMainRemote.mVolume = value;
@@ -2235,7 +2171,7 @@
}
break;
case RemoteControlClient.PLAYBACKINFO_VOLUME_MAX:
- mcse.mPlaybackVolumeMax = value;
+ prse.mPlaybackVolumeMax = value;
synchronized (mMainRemote) {
if (rccId == mMainRemote.mRccId) {
mMainRemote.mVolumeMax = value;
@@ -2244,7 +2180,7 @@
}
break;
case RemoteControlClient.PLAYBACKINFO_VOLUME_HANDLING:
- mcse.mPlaybackVolumeHandling = value;
+ prse.mPlaybackVolumeHandling = value;
synchronized (mMainRemote) {
if (rccId == mMainRemote.mRccId) {
mMainRemote.mVolumeHandling = value;
@@ -2253,7 +2189,7 @@
}
break;
case RemoteControlClient.PLAYBACKINFO_USES_STREAM:
- mcse.mPlaybackStream = value;
+ prse.mPlaybackStream = value;
break;
default:
Log.e(TAG, "unhandled key " + key + " for RCC " + rccId);
@@ -2264,7 +2200,7 @@
}//for
} catch (ArrayIndexOutOfBoundsException e) {
// not expected to happen, indicates improper concurrent modification
- Log.e(TAG, "Wrong index mMCStack on onNewPlaybackInfoForRcc, lock error? ", e);
+ Log.e(TAG, "Wrong index mPRStack on onNewPlaybackInfoForRcc, lock error? ", e);
}
}
}
@@ -2272,21 +2208,21 @@
protected void setPlaybackStateForRcc(int rccId, int state, long timeMs, float speed) {
sendMsg(mEventHandler, MSG_RCC_NEW_PLAYBACK_STATE, SENDMSG_QUEUE,
rccId /* arg1 */, state /* arg2 */,
- new MediaController.RccPlaybackState(state, timeMs, speed) /* obj */, 0 /* delay */);
+ new PlayerRecord.RccPlaybackState(state, timeMs, speed) /* obj */, 0 /* delay */);
}
private void onNewPlaybackStateForRcc(int rccId, int state,
- MediaController.RccPlaybackState newState) {
+ PlayerRecord.RccPlaybackState newState) {
if(DEBUG_RC) Log.d(TAG, "onNewPlaybackStateForRcc(id=" + rccId + ", state=" + state
+ ", time=" + newState.mPositionMs + ", speed=" + newState.mSpeed + ")");
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
// iterating from top of stack as playback information changes are more likely
// on entries at the top of the remote control stack
try {
- for (int index = mMCStack.size()-1; index >= 0; index--) {
- final MediaController mcse = mMCStack.elementAt(index);
- if (mcse.mRccId == rccId) {
- mcse.mPlaybackState = newState;
+ for (int index = mPRStack.size()-1; index >= 0; index--) {
+ final PlayerRecord prse = mPRStack.elementAt(index);
+ if (prse.getRccId() == rccId) {
+ prse.mPlaybackState = newState;
synchronized (mMainRemote) {
if (rccId == mMainRemote.mRccId) {
mMainRemoteIsActive = isPlaystateActive(state);
@@ -2303,7 +2239,7 @@
}//for
} catch (ArrayIndexOutOfBoundsException e) {
// not expected to happen, indicates improper concurrent modification
- Log.e(TAG, "Wrong index on mMCStack in onNewPlaybackStateForRcc, lock error? ", e);
+ Log.e(TAG, "Wrong index on mPRStack in onNewPlaybackStateForRcc, lock error? ", e);
}
}
}
@@ -2315,15 +2251,15 @@
// handler for MSG_RCC_NEW_VOLUME_OBS
private void onRegisterVolumeObserverForRcc(int rccId, IRemoteVolumeObserver rvo) {
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
// The stack traversal order doesn't matter because there is only one stack entry
// with this RCC ID, but the matching ID is more likely at the top of the stack, so
// start iterating from the top.
try {
- for (int index = mMCStack.size()-1; index >= 0; index--) {
- final MediaController mcse = mMCStack.elementAt(index);
- if (mcse.mRccId == rccId) {
- mcse.mRemoteVolumeObs = rvo;
+ for (int index = mPRStack.size()-1; index >= 0; index--) {
+ final PlayerRecord prse = mPRStack.elementAt(index);
+ if (prse.getRccId() == rccId) {
+ prse.mRemoteVolumeObs = rvo;
break;
}
}
@@ -2341,21 +2277,21 @@
* @return false if no remote playing is currently playing
*/
protected boolean checkUpdateRemoteStateIfActive(int streamType) {
- synchronized(mMCStack) {
+ synchronized(mPRStack) {
// iterating from top of stack as active playback is more likely on entries at the top
try {
- for (int index = mMCStack.size()-1; index >= 0; index--) {
- final MediaController mcse = mMCStack.elementAt(index);
- if ((mcse.mPlaybackType == RemoteControlClient.PLAYBACK_TYPE_REMOTE)
- && isPlaystateActive(mcse.mPlaybackState.mState)
- && (mcse.mPlaybackStream == streamType)) {
+ for (int index = mPRStack.size()-1; index >= 0; index--) {
+ final PlayerRecord prse = mPRStack.elementAt(index);
+ if ((prse.mPlaybackType == RemoteControlClient.PLAYBACK_TYPE_REMOTE)
+ && isPlaystateActive(prse.mPlaybackState.mState)
+ && (prse.mPlaybackStream == streamType)) {
if (DEBUG_RC) Log.d(TAG, "remote playback active on stream " + streamType
- + ", vol =" + mcse.mPlaybackVolume);
+ + ", vol =" + prse.mPlaybackVolume);
synchronized (mMainRemote) {
- mMainRemote.mRccId = mcse.mRccId;
- mMainRemote.mVolume = mcse.mPlaybackVolume;
- mMainRemote.mVolumeMax = mcse.mPlaybackVolumeMax;
- mMainRemote.mVolumeHandling = mcse.mPlaybackVolumeHandling;
+ mMainRemote.mRccId = prse.getRccId();
+ mMainRemote.mVolume = prse.mPlaybackVolume;
+ mMainRemote.mVolumeMax = prse.mPlaybackVolumeMax;
+ mMainRemote.mVolumeHandling = prse.mPlaybackVolumeHandling;
mMainRemoteIsActive = true;
}
return true;
@@ -2422,16 +2358,16 @@
return;
}
IRemoteVolumeObserver rvo = null;
- synchronized (mMCStack) {
+ synchronized (mPRStack) {
// The stack traversal order doesn't matter because there is only one stack entry
// with this RCC ID, but the matching ID is more likely at the top of the stack, so
// start iterating from the top.
try {
- for (int index = mMCStack.size()-1; index >= 0; index--) {
- final MediaController mcse = mMCStack.elementAt(index);
+ for (int index = mPRStack.size()-1; index >= 0; index--) {
+ final PlayerRecord prse = mPRStack.elementAt(index);
//FIXME OPTIMIZE store this info in mMainRemote so we don't have to iterate?
- if (mcse.mRccId == rccId) {
- rvo = mcse.mRemoteVolumeObs;
+ if (prse.getRccId() == rccId) {
+ rvo = prse.mRemoteVolumeObs;
break;
}
}
@@ -2477,16 +2413,16 @@
rccId = mMainRemote.mRccId;
}
IRemoteVolumeObserver rvo = null;
- synchronized (mMCStack) {
+ synchronized (mPRStack) {
// The stack traversal order doesn't matter because there is only one stack entry
// with this RCC ID, but the matching ID is more likely at the top of the stack, so
// start iterating from the top.
try {
- for (int index = mMCStack.size()-1; index >= 0; index--) {
- final MediaController mcse = mMCStack.elementAt(index);
+ for (int index = mPRStack.size()-1; index >= 0; index--) {
+ final PlayerRecord prse = mPRStack.elementAt(index);
//FIXME OPTIMIZE store this info in mMainRemote so we don't have to iterate?
- if (mcse.mRccId == rccId) {
- rvo = mcse.mRemoteVolumeObs;
+ if (prse.getRccId() == rccId) {
+ rvo = prse.mRemoteVolumeObs;
break;
}
}
@@ -2509,7 +2445,7 @@
* have their volume controlled. In this implementation this is only to reset whether
* VolumePanel should display remote volumes
*/
- private void postReevaluateRemote() {
+ protected void postReevaluateRemote() {
sendMsg(mEventHandler, MSG_REEVALUATE_REMOTE, SENDMSG_QUEUE, 0, 0, null, 0);
}
@@ -2517,13 +2453,13 @@
if (DEBUG_VOL) { Log.w(TAG, "onReevaluateRemote()"); }
// is there a registered RemoteControlClient that is handling remote playback
boolean hasRemotePlayback = false;
- synchronized (mMCStack) {
+ synchronized (mPRStack) {
// iteration stops when PLAYBACK_TYPE_REMOTE is found, so remote control stack
// traversal order doesn't matter
- Iterator<MediaController> stackIterator = mMCStack.iterator();
+ Iterator<PlayerRecord> stackIterator = mPRStack.iterator();
while(stackIterator.hasNext()) {
- MediaController mcse = stackIterator.next();
- if (mcse.mPlaybackType == RemoteControlClient.PLAYBACK_TYPE_REMOTE) {
+ PlayerRecord prse = stackIterator.next();
+ if (prse.mPlaybackType == RemoteControlClient.PLAYBACK_TYPE_REMOTE) {
hasRemotePlayback = true;
break;
}
diff --git a/media/java/android/media/PlayerRecord.java b/media/java/android/media/PlayerRecord.java
new file mode 100644
index 0000000..a79b0ed
--- /dev/null
+++ b/media/java/android/media/PlayerRecord.java
@@ -0,0 +1,354 @@
+/*
+ * 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.media;
+
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.IBinder.DeathRecipient;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.io.PrintWriter;
+
+/**
+ * @hide
+ * Class to handle all the information about a media player, encapsulating information
+ * about its use RemoteControlClient, playback type and volume... The lifecycle of each
+ * instance is managed by android.media.MediaFocusControl, from its addition to the player stack
+ * stack to its release.
+ */
+class PlayerRecord implements DeathRecipient {
+
+ // on purpose not using this classe's name, as it will only be used from MediaFocusControl
+ private static final String TAG = "MediaFocusControl";
+ private static final boolean DEBUG = false;
+
+ /**
+ * A global counter for RemoteControlClient identifiers
+ */
+ private static int sLastRccId = 0;
+
+ public static MediaFocusControl sController;
+
+ /**
+ * The target for the ACTION_MEDIA_BUTTON events.
+ * Always non null. //FIXME verify
+ */
+ final private PendingIntent mMediaIntent;
+ /**
+ * The registered media button event receiver.
+ */
+ final private ComponentName mReceiverComponent;
+
+ private int mRccId = RemoteControlClient.RCSE_ID_UNREGISTERED;
+
+ private IBinder mToken;
+ private String mCallingPackageName;
+ private int mCallingUid;
+ /**
+ * Provides access to the information to display on the remote control.
+ * May be null (when a media button event receiver is registered,
+ * but no remote control client has been registered) */
+ private IRemoteControlClient mRcClient;
+ private RcClientDeathHandler mRcClientDeathHandler;
+ /**
+ * Information only used for non-local playback
+ */
+ //FIXME private?
+ public int mPlaybackType;
+ public int mPlaybackVolume;
+ public int mPlaybackVolumeMax;
+ public int mPlaybackVolumeHandling;
+ public int mPlaybackStream;
+ public RccPlaybackState mPlaybackState;
+ public IRemoteVolumeObserver mRemoteVolumeObs;
+
+
+ protected static class RccPlaybackState {
+ public int mState;
+ public long mPositionMs;
+ public float mSpeed;
+
+ public RccPlaybackState(int state, long positionMs, float speed) {
+ mState = state;
+ mPositionMs = positionMs;
+ mSpeed = speed;
+ }
+
+ public void reset() {
+ mState = RemoteControlClient.PLAYSTATE_STOPPED;
+ mPositionMs = RemoteControlClient.PLAYBACK_POSITION_INVALID;
+ mSpeed = RemoteControlClient.PLAYBACK_SPEED_1X;
+ }
+
+ @Override
+ public String toString() {
+ return stateToString() + ", " + posToString() + ", " + mSpeed + "X";
+ }
+
+ private String posToString() {
+ if (mPositionMs == RemoteControlClient.PLAYBACK_POSITION_INVALID) {
+ return "PLAYBACK_POSITION_INVALID";
+ } else if (mPositionMs == RemoteControlClient.PLAYBACK_POSITION_ALWAYS_UNKNOWN) {
+ return "PLAYBACK_POSITION_ALWAYS_UNKNOWN";
+ } else {
+ return (String.valueOf(mPositionMs) + "ms");
+ }
+ }
+
+ private String stateToString() {
+ switch (mState) {
+ case RemoteControlClient.PLAYSTATE_NONE:
+ return "PLAYSTATE_NONE";
+ case RemoteControlClient.PLAYSTATE_STOPPED:
+ return "PLAYSTATE_STOPPED";
+ case RemoteControlClient.PLAYSTATE_PAUSED:
+ return "PLAYSTATE_PAUSED";
+ case RemoteControlClient.PLAYSTATE_PLAYING:
+ return "PLAYSTATE_PLAYING";
+ case RemoteControlClient.PLAYSTATE_FAST_FORWARDING:
+ return "PLAYSTATE_FAST_FORWARDING";
+ case RemoteControlClient.PLAYSTATE_REWINDING:
+ return "PLAYSTATE_REWINDING";
+ case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS:
+ return "PLAYSTATE_SKIPPING_FORWARDS";
+ case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS:
+ return "PLAYSTATE_SKIPPING_BACKWARDS";
+ case RemoteControlClient.PLAYSTATE_BUFFERING:
+ return "PLAYSTATE_BUFFERING";
+ case RemoteControlClient.PLAYSTATE_ERROR:
+ return "PLAYSTATE_ERROR";
+ default:
+ return "[invalid playstate]";
+ }
+ }
+ }
+
+
+ /**
+ * Inner class to monitor remote control client deaths, and remove the client for the
+ * remote control stack if necessary.
+ */
+ private class RcClientDeathHandler implements IBinder.DeathRecipient {
+ final private IBinder mCb; // To be notified of client's death
+ //FIXME needed?
+ final private PendingIntent mMediaIntent;
+
+ RcClientDeathHandler(IBinder cb, PendingIntent pi) {
+ mCb = cb;
+ mMediaIntent = pi;
+ }
+
+ public void binderDied() {
+ Log.w(TAG, " RemoteControlClient died");
+ // remote control client died, make sure the displays don't use it anymore
+ // by setting its remote control client to null
+ sController.registerRemoteControlClient(mMediaIntent, null/*rcClient*/, null/*ignored*/);
+ // the dead client was maybe handling remote playback, the controller should reevaluate
+ sController.postReevaluateRemote();
+ }
+
+ public IBinder getBinder() {
+ return mCb;
+ }
+ }
+
+
+ protected static class RemotePlaybackState {
+ int mRccId;
+ int mVolume;
+ int mVolumeMax;
+ int mVolumeHandling;
+
+ protected RemotePlaybackState(int id, int vol, int volMax) {
+ mRccId = id;
+ mVolume = vol;
+ mVolumeMax = volMax;
+ mVolumeHandling = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME_HANDLING;
+ }
+ }
+
+
+ void dump(PrintWriter pw, boolean registrationInfo) {
+ if (registrationInfo) {
+ pw.println(" pi: " + mMediaIntent +
+ " -- pack: " + mCallingPackageName +
+ " -- ercvr: " + mReceiverComponent +
+ " -- client: " + mRcClient +
+ " -- uid: " + mCallingUid +
+ " -- type: " + mPlaybackType +
+ " state: " + mPlaybackState);
+ } else {
+ // emphasis on state
+ pw.println(" uid: " + mCallingUid +
+ " -- id: " + mRccId +
+ " -- type: " + mPlaybackType +
+ " -- state: " + mPlaybackState +
+ " -- vol handling: " + mPlaybackVolumeHandling +
+ " -- vol: " + mPlaybackVolume +
+ " -- volMax: " + mPlaybackVolumeMax +
+ " -- volObs: " + mRemoteVolumeObs);
+ }
+ }
+
+
+ static protected void setMediaFocusControl(MediaFocusControl mfc) {
+ sController = mfc;
+ }
+
+ /** precondition: mediaIntent != null */
+ protected PlayerRecord(PendingIntent mediaIntent, ComponentName eventReceiver, IBinder token)
+ {
+ mMediaIntent = mediaIntent;
+ mReceiverComponent = eventReceiver;
+ mToken = token;
+ mCallingUid = -1;
+ mRcClient = null;
+ mRccId = ++sLastRccId;
+ mPlaybackState = new RccPlaybackState(
+ RemoteControlClient.PLAYSTATE_STOPPED,
+ RemoteControlClient.PLAYBACK_POSITION_INVALID,
+ RemoteControlClient.PLAYBACK_SPEED_1X);
+
+ resetPlaybackInfo();
+ if (mToken != null) {
+ try {
+ mToken.linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ sController.unregisterMediaButtonIntentAsync(mMediaIntent);
+ }
+ }
+ }
+
+ //---------------------------------------------
+ // Accessors
+ protected int getRccId() {
+ return mRccId;
+ }
+
+ protected IRemoteControlClient getRcc() {
+ return mRcClient;
+ }
+
+ protected ComponentName getMediaButtonReceiver() {
+ return mReceiverComponent;
+ }
+
+ protected PendingIntent getMediaButtonIntent() {
+ return mMediaIntent;
+ }
+
+ // FIXME this is only used when comparing with the audio focus owner calling package name,
+ // accessor to be removed once audio focus and media button owner are dissociated
+ protected String getCallingPackageName() {
+ return mCallingPackageName;
+ }
+
+ // FIXME this is only used when comparing with the audio focus owner calling package name,
+ // accessor to be removed once audio focus and media button owner are dissociated
+ protected int getCallingUid() {
+ return mCallingUid;
+ }
+
+ protected boolean hasMatchingMediaButtonIntent(PendingIntent pi) {
+ return mMediaIntent.equals(pi);
+ }
+
+ //---------------------------------------------
+ // Modify the records stored in the instance
+ protected void resetControllerInfoForRcc(IRemoteControlClient rcClient,
+ String callingPackageName, int uid) {
+ // already had a remote control client?
+ if (mRcClientDeathHandler != null) {
+ // stop monitoring the old client's death
+ unlinkToRcClientDeath();
+ }
+ // save the new remote control client
+ mRcClient = rcClient;
+ mCallingPackageName = callingPackageName;
+ mCallingUid = uid;
+ if (rcClient == null) {
+ // here mcse.mRcClientDeathHandler is null;
+ resetPlaybackInfo();
+ } else {
+ IBinder b = mRcClient.asBinder();
+ RcClientDeathHandler rcdh =
+ new RcClientDeathHandler(b, mMediaIntent);
+ try {
+ b.linkToDeath(rcdh, 0);
+ } catch (RemoteException e) {
+ // remote control client is DOA, disqualify it
+ Log.w(TAG, "registerRemoteControlClient() has a dead client " + b);
+ mRcClient = null;
+ }
+ mRcClientDeathHandler = rcdh;
+ }
+ }
+
+ protected void resetControllerInfoForNoRcc() {
+ // stop monitoring the RCC death
+ unlinkToRcClientDeath();
+ // reset the RCC-related fields
+ mRcClient = null;
+ mCallingPackageName = null;
+ }
+
+ public void resetPlaybackInfo() {
+ mPlaybackType = RemoteControlClient.PLAYBACK_TYPE_LOCAL;
+ mPlaybackVolume = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME;
+ mPlaybackVolumeMax = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME;
+ mPlaybackVolumeHandling = RemoteControlClient.DEFAULT_PLAYBACK_VOLUME_HANDLING;
+ mPlaybackStream = AudioManager.STREAM_MUSIC;
+ mPlaybackState.reset();
+ mRemoteVolumeObs = null;
+ }
+
+ //---------------------------------------------
+ public void unlinkToRcClientDeath() {
+ if ((mRcClientDeathHandler != null) && (mRcClientDeathHandler.mCb != null)) {
+ try {
+ mRcClientDeathHandler.mCb.unlinkToDeath(mRcClientDeathHandler, 0);
+ mRcClientDeathHandler = null;
+ } catch (java.util.NoSuchElementException e) {
+ // not much we can do here
+ Log.e(TAG, "Error in unlinkToRcClientDeath()", e);
+ }
+ }
+ }
+
+ // FIXME rename to "release"? (as in FocusRequester class)
+ public void destroy() {
+ unlinkToRcClientDeath();
+ if (mToken != null) {
+ mToken.unlinkToDeath(this, 0);
+ mToken = null;
+ }
+ }
+
+ @Override
+ public void binderDied() {
+ sController.unregisterMediaButtonIntentAsync(mMediaIntent);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ destroy(); // unlink exception handled inside method
+ super.finalize();
+ }
+}
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 15ae238..fce3fd0 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -202,12 +202,17 @@
public void setServer(MtpServer server) {
mServer = server;
+ // always unregister before registering
+ try {
+ mContext.unregisterReceiver(mBatteryReceiver);
+ } catch (IllegalArgumentException e) {
+ // wasn't previously registered, ignore
+ }
+
// register for battery notifications when we are connected
if (server != null) {
mContext.registerReceiver(mBatteryReceiver,
new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
- } else {
- mContext.unregisterReceiver(mBatteryReceiver);
}
}
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index b2fb2df..d04b1f8 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -27,6 +27,8 @@
#include "jni.h"
#include "JNIHelp.h"
+#include <cutils/compiler.h>
+
#include <gui/Surface.h>
#include <media/ICrypto.h>
@@ -738,6 +740,10 @@
} else if (numBytesOfClearDataObj != NULL
&& env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
err = -ERANGE;
+ // subSamples array may silently overflow if number of samples are too large. Use
+ // INT32_MAX as maximum allocation size may be less than SIZE_MAX on some platforms
+ } else if ( CC_UNLIKELY(numSubSamples >= INT32_MAX / sizeof(*subSamples)) ) {
+ err = -EINVAL;
} else {
jboolean isCopy;
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 052d97d..1dbaa3a 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -100,6 +100,16 @@
jint kKeyTypeRelease;
} gKeyTypes;
+struct CertificateTypes {
+ jint kCertificateTypeNone;
+ jint kCertificateTypeX509;
+} gCertificateTypes;
+
+struct CertificateFields {
+ jfieldID wrappedPrivateKey;
+ jfieldID certificateData;
+};
+
struct fields_t {
jfieldID context;
jmethodID post_event;
@@ -110,6 +120,11 @@
SetFields set;
IteratorFields iterator;
EntryFields entry;
+ CertificateFields certificate;
+ jclass certificateClassId;
+ jclass hashmapClassId;
+ jclass arraylistClassId;
+ jclass stringClassId;
};
static fields_t gFields;
@@ -406,8 +421,7 @@
*/
static KeyedVector<String8, String8> HashMapToKeyedVector(JNIEnv *env, jobject &hashMap) {
- jclass clazz;
- FIND_CLASS(clazz, "java/lang/String");
+ jclass clazz = gFields.stringClassId;
KeyedVector<String8, String8> keyedVector;
jobject entrySet = env->CallObjectMethod(hashMap, gFields.hashmap.entrySet);
@@ -450,8 +464,7 @@
}
static jobject KeyedVectorToHashMap (JNIEnv *env, KeyedVector<String8, String8> const &map) {
- jclass clazz;
- FIND_CLASS(clazz, "java/util/HashMap");
+ jclass clazz = gFields.hashmapClassId;
jobject hashMap = env->NewObject(clazz, gFields.hashmap.init);
for (size_t i = 0; i < map.size(); ++i) {
jstring jkey = env->NewStringUTF(map.keyAt(i).string());
@@ -465,8 +478,7 @@
static jobject ListOfVectorsToArrayListOfByteArray(JNIEnv *env,
List<Vector<uint8_t> > list) {
- jclass clazz;
- FIND_CLASS(clazz, "java/util/ArrayList");
+ jclass clazz = gFields.arraylistClassId;
jobject arrayList = env->NewObject(clazz, gFields.arraylist.init);
List<Vector<uint8_t> >::iterator iter = list.begin();
while (iter != list.end()) {
@@ -542,6 +554,11 @@
GET_STATIC_FIELD_ID(field, clazz, "KEY_TYPE_RELEASE", "I");
gKeyTypes.kKeyTypeRelease = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_NONE", "I");
+ gCertificateTypes.kCertificateTypeNone = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
+ gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
+
FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
@@ -550,6 +567,11 @@
GET_FIELD_ID(gFields.provisionRequest.data, clazz, "mData", "[B");
GET_FIELD_ID(gFields.provisionRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
+ FIND_CLASS(clazz, "android/media/MediaDrm$Certificate");
+ GET_FIELD_ID(gFields.certificate.wrappedPrivateKey, clazz, "mWrappedKey", "[B");
+ GET_FIELD_ID(gFields.certificate.certificateData, clazz, "mCertificateData", "[B");
+ gFields.certificateClassId = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
+
FIND_CLASS(clazz, "java/util/ArrayList");
GET_METHOD_ID(gFields.arraylist.init, clazz, "<init>", "()V");
GET_METHOD_ID(gFields.arraylist.add, clazz, "add", "(Ljava/lang/Object;)Z");
@@ -571,6 +593,15 @@
FIND_CLASS(clazz, "java/util/Map$Entry");
GET_METHOD_ID(gFields.entry.getKey, clazz, "getKey", "()Ljava/lang/Object;");
GET_METHOD_ID(gFields.entry.getValue, clazz, "getValue", "()Ljava/lang/Object;");
+
+ FIND_CLASS(clazz, "java/util/HashMap");
+ gFields.hashmapClassId = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
+
+ FIND_CLASS(clazz, "java/lang/String");
+ gFields.stringClassId = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
+
+ FIND_CLASS(clazz, "java/util/ArrayList");
+ gFields.arraylistClassId = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
}
static void android_media_MediaDrm_native_setup(
@@ -826,8 +857,8 @@
return KeyedVectorToHashMap(env, infoMap);
}
-static jobject android_media_MediaDrm_getProvisionRequest(
- JNIEnv *env, jobject thiz) {
+static jobject android_media_MediaDrm_getProvisionRequestNative(
+ JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
sp<IDrm> drm = GetDrm(env, thiz);
if (drm == NULL) {
@@ -839,7 +870,17 @@
Vector<uint8_t> request;
String8 defaultUrl;
- status_t err = drm->getProvisionRequest(request, defaultUrl);
+ String8 certType;
+ if (jcertType == gCertificateTypes.kCertificateTypeX509) {
+ certType = "X.509";
+ } else if (jcertType == gCertificateTypes.kCertificateTypeNone) {
+ certType = "none";
+ } else {
+ certType = "invalid";
+ }
+
+ String8 certAuthority = JStringToString8(env, jcertAuthority);
+ status_t err = drm->getProvisionRequest(certType, certAuthority, request, defaultUrl);
if (throwExceptionAsNecessary(env, err, "Failed to get provision request")) {
return NULL;
@@ -863,27 +904,43 @@
return provisionObj;
}
-static void android_media_MediaDrm_provideProvisionResponse(
+static jobject android_media_MediaDrm_provideProvisionResponseNative(
JNIEnv *env, jobject thiz, jbyteArray jresponse) {
sp<IDrm> drm = GetDrm(env, thiz);
if (drm == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"MediaDrm obj is null");
- return;
+ return NULL;
}
if (jresponse == NULL) {
jniThrowException(env, "java/lang/IllegalArgumentException",
"provision response is null");
- return;
+ return NULL;
}
Vector<uint8_t> response(JByteArrayToVector(env, jresponse));
+ Vector<uint8_t> certificate, wrappedKey;
- status_t err = drm->provideProvisionResponse(response);
+ status_t err = drm->provideProvisionResponse(response, certificate, wrappedKey);
+
+ // Fill out return obj
+ jclass clazz = gFields.certificateClassId;
+
+ jobject certificateObj = NULL;
+
+ if (clazz && certificate.size() && wrappedKey.size()) {
+ certificateObj = env->AllocObject(clazz);
+ jbyteArray jcertificate = VectorToJByteArray(env, certificate);
+ env->SetObjectField(certificateObj, gFields.certificate.certificateData, jcertificate);
+
+ jbyteArray jwrappedKey = VectorToJByteArray(env, wrappedKey);
+ env->SetObjectField(certificateObj, gFields.certificate.wrappedPrivateKey, jwrappedKey);
+ }
throwExceptionAsNecessary(env, err, "Failed to handle provision response");
+ return certificateObj;
}
static jobject android_media_MediaDrm_getSecureStops(
@@ -1209,6 +1266,38 @@
}
+static jbyteArray android_media_MediaDrm_signRSANative(
+ JNIEnv *env, jobject thiz, jobject jdrm, jbyteArray jsessionId,
+ jstring jalgorithm, jbyteArray jwrappedKey, jbyteArray jmessage) {
+
+ sp<IDrm> drm = GetDrm(env, jdrm);
+
+ if (!CheckSession(env, drm, jsessionId)) {
+ return NULL;
+ }
+
+ if (jalgorithm == NULL || jwrappedKey == NULL || jmessage == NULL) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "required argument is null");
+ return NULL;
+ }
+
+ Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
+ String8 algorithm = JStringToString8(env, jalgorithm);
+ Vector<uint8_t> wrappedKey(JByteArrayToVector(env, jwrappedKey));
+ Vector<uint8_t> message(JByteArrayToVector(env, jmessage));
+ Vector<uint8_t> signature;
+
+ status_t err = drm->signRSA(sessionId, algorithm, message, wrappedKey, signature);
+
+ if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
+ return NULL;
+ }
+
+ return VectorToJByteArray(env, signature);
+}
+
+
static JNINativeMethod gMethods[] = {
{ "release", "()V", (void *)android_media_MediaDrm_release },
{ "native_init", "()V", (void *)android_media_MediaDrm_native_init },
@@ -1244,11 +1333,11 @@
{ "queryKeyStatus", "([B)Ljava/util/HashMap;",
(void *)android_media_MediaDrm_queryKeyStatus },
- { "getProvisionRequest", "()Landroid/media/MediaDrm$ProvisionRequest;",
- (void *)android_media_MediaDrm_getProvisionRequest },
+ { "getProvisionRequestNative", "(ILjava/lang/String;)Landroid/media/MediaDrm$ProvisionRequest;",
+ (void *)android_media_MediaDrm_getProvisionRequestNative },
- { "provideProvisionResponse", "([B)V",
- (void *)android_media_MediaDrm_provideProvisionResponse },
+ { "provideProvisionResponseNative", "([B)Landroid/media/MediaDrm$Certificate;",
+ (void *)android_media_MediaDrm_provideProvisionResponseNative },
{ "getSecureStops", "()Ljava/util/List;",
(void *)android_media_MediaDrm_getSecureStops },
@@ -1287,6 +1376,9 @@
{ "verifyNative", "(Landroid/media/MediaDrm;[B[B[B[B)Z",
(void *)android_media_MediaDrm_verifyNative },
+
+ { "signRSANative", "(Landroid/media/MediaDrm;[BLjava/lang/String;[B[B)[B",
+ (void *)android_media_MediaDrm_signRSANative },
};
int register_android_media_Drm(JNIEnv *env) {
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index a78f16d..3dbf77b 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -87,7 +87,7 @@
jbyteArray byteArrayObj = env->NewByteArray(size);
env->DeleteLocalRef(env->GetObjectClass(mDataSource));
env->DeleteLocalRef(env->GetObjectClass(byteArrayObj));
- ssize_t numread = env->CallIntMethod(mDataSource, mReadMethod, offset, byteArrayObj, size);
+ ssize_t numread = env->CallIntMethod(mDataSource, mReadMethod, offset, byteArrayObj, (jint)size);
env->GetByteArrayRegion(byteArrayObj, 0, size, (jbyte*) buffer);
env->DeleteLocalRef(byteArrayObj);
if (env->ExceptionCheck()) {
@@ -632,7 +632,7 @@
env->CallVoidMethod(
cryptoInfoObj,
gFields.cryptoInfoSetID,
- numSubSamples,
+ (jint)numSubSamples,
numBytesOfPlainDataObj,
numBytesOfEncryptedDataObj,
keyObj,
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 82c6a80..0e55228 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -17,11 +17,12 @@
#define LOG_TAG "MtpDatabaseJNI"
#include "utils/Log.h"
-#include <stdio.h>
#include <assert.h>
-#include <limits.h>
-#include <unistd.h>
#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
#include "jni.h"
#include "JNIHelp.h"
@@ -393,7 +394,7 @@
// release date is stored internally as just the year
if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
char date[20];
- snprintf(date, sizeof(date), "%04lld0101T000000", longValue);
+ snprintf(date, sizeof(date), "%04" PRId64 "0101T000000", longValue);
packet.putString(date);
goto out;
}
@@ -657,7 +658,7 @@
return result;
}
-MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
+MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty /*property*/) {
return -1;
}
@@ -1151,7 +1152,7 @@
}
static jstring
-android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject thiz, jlong seconds)
+android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject /*thiz*/, jlong seconds)
{
char date[20];
formatDateTime(seconds, date, sizeof(date));
diff --git a/media/lib/Android.mk b/media/lib/remotedisplay/Android.mk
similarity index 93%
rename from media/lib/Android.mk
rename to media/lib/remotedisplay/Android.mk
index 50799a6..ea1ac2b 100644
--- a/media/lib/Android.mk
+++ b/media/lib/remotedisplay/Android.mk
@@ -15,7 +15,7 @@
#
LOCAL_PATH := $(call my-dir)
-# the library
+# the remotedisplay library
# ============================================================
include $(CLEAR_VARS)
@@ -23,7 +23,7 @@
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := \
- $(call all-subdir-java-files) \
+ $(call all-java-files-under, java) \
$(call all-aidl-files-under, java)
include $(BUILD_JAVA_LIBRARY)
diff --git a/media/lib/README.txt b/media/lib/remotedisplay/README.txt
similarity index 99%
rename from media/lib/README.txt
rename to media/lib/remotedisplay/README.txt
index cade3df..5738dbe 100644
--- a/media/lib/README.txt
+++ b/media/lib/remotedisplay/README.txt
@@ -25,4 +25,3 @@
library is a compromise to make new capabilities available to the system
without exposing the full surface area of the support library media
route provider protocol.
-
diff --git a/media/lib/com.android.media.remotedisplay.xml b/media/lib/remotedisplay/com.android.media.remotedisplay.xml
similarity index 100%
rename from media/lib/com.android.media.remotedisplay.xml
rename to media/lib/remotedisplay/com.android.media.remotedisplay.xml
diff --git a/media/lib/java/com/android/media/remotedisplay/RemoteDisplay.java b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplay.java
similarity index 100%
rename from media/lib/java/com/android/media/remotedisplay/RemoteDisplay.java
rename to media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplay.java
diff --git a/media/lib/java/com/android/media/remotedisplay/RemoteDisplayProvider.java b/media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
similarity index 100%
rename from media/lib/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
rename to media/lib/remotedisplay/java/com/android/media/remotedisplay/RemoteDisplayProvider.java
diff --git a/media/lib/Android.mk b/media/lib/signer/Android.mk
similarity index 76%
copy from media/lib/Android.mk
copy to media/lib/signer/Android.mk
index 50799a6..4c3772f 100644
--- a/media/lib/Android.mk
+++ b/media/lib/signer/Android.mk
@@ -15,24 +15,23 @@
#
LOCAL_PATH := $(call my-dir)
-# the library
+# the mediadrm signer library
# ============================================================
include $(CLEAR_VARS)
-LOCAL_MODULE:= com.android.media.remotedisplay
+LOCAL_MODULE:= com.android.mediadrm.signer
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := \
- $(call all-subdir-java-files) \
- $(call all-aidl-files-under, java)
+ $(call all-java-files-under, java)
-include $(BUILD_JAVA_LIBRARY)
+include $(BUILD_STATIC_JAVA_LIBRARY)
-# ==== com.android.media.remotedisplay.xml lib def ========================
+# ==== com.android.mediadrm.signer.xml lib def ========================
include $(CLEAR_VARS)
-LOCAL_MODULE := com.android.media.remotedisplay.xml
+LOCAL_MODULE := com.android.mediadrm.signer.xml
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
diff --git a/media/lib/signer/README.txt b/media/lib/signer/README.txt
new file mode 100644
index 0000000..362ab8e
--- /dev/null
+++ b/media/lib/signer/README.txt
@@ -0,0 +1,28 @@
+This library (com.android.mediadrm.signer.jar) is a shared java library
+containing classes required by unbundled apps running on devices that use
+the certficate provisioning and private key signing capabilities provided
+by the MediaDrm API.
+
+--- Rules of this library ---
+o This library is effectively a PUBLIC API for unbundled CAST receivers
+ that may be distributed outside the system image. So it MUST BE API STABLE.
+ You can add but not remove. The rules are the same as for the
+ public platform SDK API.
+o This library can see and instantiate internal platform classes, but it must not
+ expose them in any public method (or by extending them via inheritance). This would
+ break clients of the library because they cannot see the internal platform classes.
+
+This library is distributed in the system image, and loaded as
+a shared library. So you can change the implementation, but not
+the interface. In this way it is like framework.jar.
+
+--- Why does this library exist? ---
+
+Unbundled apps cannot use internal platform classes.
+
+This library will eventually be replaced when the provisioned certificate-
+based signing infrastructure that is currently defined in the support library
+is reintegrated with the framework in a new API. That API isn't ready yet so
+this library is a compromise to make new capabilities available to the system
+without exposing the full surface area of the support library.
+
diff --git a/core/res/res/drawable/item_background_borderless_quantum_dark.xml b/media/lib/signer/com.android.mediadrm.signer.xml
similarity index 74%
copy from core/res/res/drawable/item_background_borderless_quantum_dark.xml
copy to media/lib/signer/com.android.mediadrm.signer.xml
index 3f32850..b5b1f09 100644
--- a/core/res/res/drawable/item_background_borderless_quantum_dark.xml
+++ b/media/lib/signer/com.android.mediadrm.signer.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!-- Copyright (C) 2013 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.
@@ -14,5 +14,7 @@
limitations under the License.
-->
-<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="@color/lighter_gray" />
+<permissions>
+ <library name="com.android.media.drm.signer"
+ file="/system/framework/com.android.media.drm.signer.jar" />
+</permissions>
diff --git a/media/lib/signer/java/com/android/mediadrm/signer/MediaDrmSigner.java b/media/lib/signer/java/com/android/mediadrm/signer/MediaDrmSigner.java
new file mode 100644
index 0000000..d971afb
--- /dev/null
+++ b/media/lib/signer/java/com/android/mediadrm/signer/MediaDrmSigner.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2013 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.mediadrm.signer;
+
+import android.content.Context;
+import android.media.MediaDrm;
+import android.media.DeniedByServerException;
+
+/**
+ * Provides certificate request generation, response handling and
+ * signing APIs
+ */
+public final class MediaDrmSigner {
+ private MediaDrmSigner() {}
+
+ /**
+ * Specify X.509 certificate type
+ */
+ public static final int CERTIFICATE_TYPE_X509 = MediaDrm.CERTIFICATE_TYPE_X509;
+
+ /**
+ * Contains the opaque data an app uses to request a certificate from a provisioning
+ * server
+ */
+ public final static class CertificateRequest {
+ private MediaDrm.CertificateRequest mCertRequest;
+
+ CertificateRequest(MediaDrm.CertificateRequest certRequest) {
+ mCertRequest = certRequest;
+ }
+
+ /**
+ * Get the opaque message data
+ */
+ public byte[] getData() {
+ return mCertRequest.getData();
+ }
+
+ /**
+ * Get the default URL to use when sending the certificate request
+ * message to a server, if known. The app may prefer to use a different
+ * certificate server URL obtained from other sources.
+ */
+ public String getDefaultUrl() {
+ return mCertRequest.getDefaultUrl();
+ }
+ }
+
+ /**
+ * Contains the wrapped private key and public certificate data associated
+ * with a certificate.
+ */
+ public final static class Certificate {
+ private MediaDrm.Certificate mCertificate;
+
+ Certificate(MediaDrm.Certificate certificate) {
+ mCertificate = certificate;
+ }
+
+ /**
+ * Get the wrapped private key data
+ */
+ public byte[] getWrappedPrivateKey() {
+ return mCertificate.getWrappedPrivateKey();
+ }
+
+ /**
+ * Get the PEM-encoded public certificate chain
+ */
+ public byte[] getContent() {
+ return mCertificate.getContent();
+ }
+ }
+
+ /**
+ * Generate a certificate request, specifying the certificate type
+ * and authority. The response received should be passed to
+ * provideCertificateResponse.
+ *
+ * @param drm the MediaDrm object
+ * @param certType Specifies the certificate type.
+ * @param certAuthority is passed to the certificate server to specify
+ * the chain of authority.
+ */
+ public static CertificateRequest getCertificateRequest(MediaDrm drm, int certType,
+ String certAuthority) {
+ return new CertificateRequest(drm.getCertificateRequest(certType, certAuthority));
+ }
+
+ /**
+ * Process a response from the provisioning server. The response
+ * is obtained from an HTTP Post to the url provided by getCertificateRequest.
+ *
+ * The public X509 certificate chain and wrapped private key are returned
+ * in the returned Certificate objec. The certificate chain is in BIO serialized
+ * PEM format. The wrapped private key should be stored in application private
+ * storage, and used when invoking the signRSA method.
+ *
+ * @param drm the MediaDrm object
+ * @param response the opaque certificate response byte array to provide to the
+ * DRM engine plugin.
+ * @throws android.media.DeniedByServerException if the response indicates that the
+ * server rejected the request
+ */
+ public static Certificate provideCertificateResponse(MediaDrm drm, byte[] response)
+ throws DeniedByServerException {
+ return new Certificate(drm.provideCertificateResponse(response));
+ }
+
+ /**
+ * Sign data using an RSA key
+ *
+ * @param context the App context
+ * @param drm the MediaDrm object
+ * @param sessionId a sessionId obtained from openSession on the MediaDrm object
+ * @param algorithm the signing algorithm to use, e.g. "PKCS1-BlockType1"
+ * @param wrappedKey - the wrapped (encrypted) RSA private key obtained
+ * from provideCertificateResponse
+ * @param message the data for which a signature is to be computed
+ */
+ public static byte[] signRSA(Context context, MediaDrm drm, byte[] sessionId,
+ String algorithm, byte[] wrappedKey, byte[] message) {
+ return drm.signRSA(context, sessionId, algorithm, wrappedKey, message);
+ }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 43ebef4..5f3ba74 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -140,7 +140,9 @@
private int submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception {
int requestId = mCameraUser.submitRequest(request, streaming);
- assertTrue("Request IDs should be non-negative", requestId >= 0);
+ assertTrue(
+ "Request IDs should be non-negative (expected: >= 0, actual: " + requestId + ")",
+ requestId >= 0);
return requestId;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
index 3f17aa9..26498ca 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
@@ -309,7 +309,7 @@
});
// rational (n) -- in particular rational x 9
- checkKeyGetAndSetArray("android.sensor.calibrationTransform1", Rational[].class,
+ checkKeyGetAndSetArray("android.sensor.calibrationTransform", Rational[].class,
new Rational[] {
new Rational(1, 2), new Rational(3, 4), new Rational(5, 6),
new Rational(7, 8), new Rational(9, 10), new Rational(10, 11),
diff --git a/media/tests/omxjpegdecoder/Android.mk b/media/tests/omxjpegdecoder/Android.mk
index 95ae33b..b0bc5d4 100644
--- a/media/tests/omxjpegdecoder/Android.mk
+++ b/media/tests/omxjpegdecoder/Android.mk
@@ -19,7 +19,6 @@
LOCAL_SRC_FILES := \
omx_jpeg_decoder.cpp \
jpeg_decoder_bench.cpp \
- SkOmxPixelRef.cpp \
StreamSource.cpp
LOCAL_SHARED_LIBRARIES := \
diff --git a/media/tests/omxjpegdecoder/SkOmxPixelRef.cpp b/media/tests/omxjpegdecoder/SkOmxPixelRef.cpp
deleted file mode 100644
index a25e854..0000000
--- a/media/tests/omxjpegdecoder/SkOmxPixelRef.cpp
+++ /dev/null
@@ -1,46 +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.
- */
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <SkBitmap.h>
-
-#include "SkOmxPixelRef.h"
-
-using namespace android;
-
-SkOmxPixelRef::SkOmxPixelRef(SkColorTable* ctable, MediaBuffer* buffer,
- sp<MediaSource> decoder) {
- mBuffer = buffer;
- mDecoder = decoder;
- mSize = buffer->size();
- mCTable = ctable;
- SkSafeRef(mCTable);
-}
-
-SkOmxPixelRef::~SkOmxPixelRef() {
- mBuffer->release();
- CHECK_EQ(mDecoder->stop(), (status_t)OK);
- SkSafeUnref(mCTable);
-}
-
-void* SkOmxPixelRef::onLockPixels(SkColorTable** ct) {
- *ct = mCTable;
- return mBuffer->data();
-}
-
-void SkOmxPixelRef::onUnlockPixels() {
- // nothing to do
-}
diff --git a/media/tests/omxjpegdecoder/SkOmxPixelRef.h b/media/tests/omxjpegdecoder/SkOmxPixelRef.h
deleted file mode 100644
index 374604c..0000000
--- a/media/tests/omxjpegdecoder/SkOmxPixelRef.h
+++ /dev/null
@@ -1,52 +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.
- */
-
-#ifndef SKOMXPIXELREF_DEFINED
-#define SKOMXPIXELREF_DEFINED
-
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
-#include <SkPixelRef.h>
-
-namespace android {
-
-class SkOmxPixelRef : public SkPixelRef {
-public:
- SkOmxPixelRef(SkColorTable* ctable, MediaBuffer* buffer,
- sp<MediaSource> decoder);
- virtual ~SkOmxPixelRef();
-
- //! Return the allocation size for the pixels
- size_t getSize() const { return mSize; }
-
- SK_DECLARE_UNFLATTENABLE_OBJECT()
-protected:
- // overrides from SkPixelRef
- virtual void* onLockPixels(SkColorTable**);
- virtual void onUnlockPixels();
-
-private:
- MediaBuffer* mBuffer;
- sp<MediaSource> mDecoder;
- size_t mSize;
- SkColorTable* mCTable;
-
- typedef SkPixelRef INHERITED;
-};
-
-} // namespace android
-#endif // SKOMXPIXELREF_DEFINED
diff --git a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
index 53f04bc..3dd988e 100644
--- a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
+++ b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
@@ -34,7 +34,6 @@
#include <SkMallocPixelRef.h>
#include "omx_jpeg_decoder.h"
-#include "SkOmxPixelRef.h"
#include "StreamSource.h"
using namespace android;
@@ -158,10 +157,6 @@
printf("Duration in decoder->read(): %.1f (msecs). \n",
duration / 1E3 );
- /* Mark the code for now, since we attend to copy buffer to SkBitmap.
- // Install pixelRef to Bitmap.
- installPixelRef(buffer, decoder, bm);*/
-
// Copy pixels from buffer to bm.
// May need to check buffer->rawBytes() == bm->rawBytes().
CHECK_EQ(buffer->size(), bm->getSize());
@@ -172,17 +167,6 @@
return true;
}
-void OmxJpegImageDecoder::installPixelRef(MediaBuffer *buffer, sp<MediaSource> decoder,
- SkBitmap* bm) {
-
- // set bm's pixelref based on the data in buffer.
- SkAutoLockPixels alp(*bm);
- SkPixelRef* pr = new SkOmxPixelRef(NULL, buffer, decoder);
- bm->setPixelRef(pr)->unref();
- bm->lockPixels();
- return;
-}
-
void OmxJpegImageDecoder::configBitmapSize(SkBitmap* bm, SkBitmap::Config pref,
int width, int height) {
bm->setConfig(getColorSpaceConfig(pref), width, height, 0, kOpaque_SkAlphaType);
diff --git a/media/tests/omxjpegdecoder/omx_jpeg_decoder.h b/media/tests/omxjpegdecoder/omx_jpeg_decoder.h
index a313877..e431e72 100644
--- a/media/tests/omxjpegdecoder/omx_jpeg_decoder.h
+++ b/media/tests/omxjpegdecoder/omx_jpeg_decoder.h
@@ -49,8 +49,6 @@
sp<MediaSource> getDecoder(OMXClient* client, const sp<MediaSource>& source);
bool decodeSource(sp<MediaSource> decoder, const sp<MediaSource>& source,
SkBitmap* bm);
- void installPixelRef(MediaBuffer* buffer, sp<MediaSource> decoder,
- SkBitmap* bm);
void configBitmapSize(SkBitmap* bm, SkBitmap::Config pref, int width,
int height);
SkBitmap::Config getColorSpaceConfig(SkBitmap::Config pref);
diff --git a/packages/BackupRestoreConfirmation/AndroidManifest.xml b/packages/BackupRestoreConfirmation/AndroidManifest.xml
index 4fb26ae..8141fa7 100644
--- a/packages/BackupRestoreConfirmation/AndroidManifest.xml
+++ b/packages/BackupRestoreConfirmation/AndroidManifest.xml
@@ -1,20 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-** Copyright 2011, 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.
+/*
+ * Copyright (c) 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-->
-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.backupconfirm" >
diff --git a/packages/BackupRestoreConfirmation/res/values-sk/strings.xml b/packages/BackupRestoreConfirmation/res/values-sk/strings.xml
index 21e21b5..12f562b 100644
--- a/packages/BackupRestoreConfirmation/res/values-sk/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-sk/strings.xml
@@ -24,7 +24,7 @@
<string name="restore_confirm_text" msgid="7499866728030461776">"Z pripojeného počítača bolo vyžiadané úplné obnovenie všetkých údajov. Chcete túto akciu povoliť?\n\nAk ste toto obnovenie nevyžiadali vy, túto operáciu nepovoľujte. Táto akcia nahradí všetky údaje v zariadení."</string>
<string name="allow_restore_button_label" msgid="3081286752277127827">"Obnoviť údaje"</string>
<string name="deny_restore_button_label" msgid="1724367334453104378">"Neobnoviť"</string>
- <string name="current_password_text" msgid="8268189555578298067">"Zadajte svoje aktuálne heslo pre zálohu nižšie:"</string>
+ <string name="current_password_text" msgid="8268189555578298067">"Zadajte svoje aktuálne heslo záloh nižšie:"</string>
<string name="device_encryption_restore_text" msgid="1570864916855208992">"Zadajte svoje heslo na šifrovanie zariadenia nižšie."</string>
<string name="device_encryption_backup_text" msgid="5866590762672844664">"Zadajte svoje heslo na šifrovanie zariadenia nižšie. Bude tiež použité na šifrovanie archívu zálohy."</string>
<string name="backup_enc_password_text" msgid="4981585714795233099">"Zadajte heslo, ktoré sa použije pri šifrovaní údajov úplnej zálohy. Ak pole ponecháte prázdne, použije sa vaše aktuálne heslo zálohy:"</string>
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 179bcd1..6b77a7c 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -42,7 +42,7 @@
<activity
android:name=".SettingsActivity"
android:label="@string/menu_settings"
- android:theme="@android:style/Theme.Holo.Light.DialogWhenLarge"
+ android:theme="@android:style/Theme.DeviceDefault.Light.DialogWhenLarge"
android:exported="false" />
<provider
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index 28323b6..baca387 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -38,7 +38,7 @@
<string name="save_error" msgid="6167009778003223664">"Impossibile salvare il documento"</string>
<string name="create_error" msgid="3735649141335444215">"Impossibile creare la cartella"</string>
<string name="query_error" msgid="1222448261663503501">"Impossibile chiedere documenti"</string>
- <string name="root_recent" msgid="4470053704320518133">"Recente"</string>
+ <string name="root_recent" msgid="4470053704320518133">"Recenti"</string>
<string name="root_available_bytes" msgid="8568452858617033281">"<xliff:g id="SIZE">%1$s</xliff:g> liberi"</string>
<string name="root_type_service" msgid="2178854894416775409">"Servizi di archiviazione"</string>
<string name="root_type_shortcut" msgid="3318760609471618093">"Scorciatoie"</string>
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index f4e5582..42cec9c 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -44,8 +44,8 @@
<string name="root_type_shortcut" msgid="3318760609471618093">"Skróty"</string>
<string name="root_type_device" msgid="7121342474653483538">"Urządzenia"</string>
<string name="root_type_apps" msgid="8838065367985945189">"Więcej aplikacji"</string>
- <string name="pref_advanced_devices" msgid="903257239609301276">"Wyświetl urządzenia zaawansowane"</string>
- <string name="pref_file_size" msgid="2826879315743961459">"Wyświetl rozmiar pliku"</string>
+ <string name="pref_advanced_devices" msgid="903257239609301276">"Pokaż urządzenia zaawansowane"</string>
+ <string name="pref_file_size" msgid="2826879315743961459">"Pokaż rozmiar pliku"</string>
<string name="pref_device_size" msgid="3542106883278997222">"Wyświetl rozmiar urządzenia"</string>
<string name="empty" msgid="7858882803708117596">"Brak elementów"</string>
<string name="toast_no_application" msgid="1339885974067891667">"Nie można otworzyć pliku"</string>
diff --git a/packages/DocumentsUI/res/values-sw720dp/styles.xml b/packages/DocumentsUI/res/values-sw720dp/styles.xml
index 19d2ebe..8d31444 100644
--- a/packages/DocumentsUI/res/values-sw720dp/styles.xml
+++ b/packages/DocumentsUI/res/values-sw720dp/styles.xml
@@ -15,11 +15,11 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <style name="Theme" parent="@android:style/Theme.Holo.Light">
+ <style name="Theme" parent="@android:style/Theme.DeviceDefault.Light">
<item name="android:actionOverflowButtonStyle">@style/DarkerOverflow</item>
<item name="android:windowBackground">@*android:drawable/dialog_full_holo_light</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowIsTranslucent">true</item>
- <item name="android:windowAnimationStyle">@*android:style/Animation.Holo.Dialog</item>
+ <item name="android:windowAnimationStyle">@*android:style/Animation.DeviceDefault.Dialog</item>
</style>
</resources>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index 0c8f712..a416eb4 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -29,11 +29,11 @@
<!-- Normally just a redirection, but this is used to make ourselves a
dialog on large tablets -->
- <style name="Theme" parent="@android:style/Theme.Holo.Light">
+ <style name="Theme" parent="@android:style/Theme.DeviceDefault.Light">
<item name="android:actionOverflowButtonStyle">@style/DarkerOverflow</item>
</style>
- <style name="DarkerOverflow" parent="@android:style/Widget.Holo.Light.ActionButton.Overflow">
+ <style name="DarkerOverflow" parent="@android:style/Widget.DeviceDefault.Light.ActionButton.Overflow">
<item name="android:src">@drawable/ic_menu_overflow</item>
</style>
diff --git a/packages/FusedLocation/res/values-fr-rCA/strings.xml b/packages/FusedLocation/res/values-fr-rCA/strings.xml
index 0d2cccc..c7d33af 100644
--- a/packages/FusedLocation/res/values-fr-rCA/strings.xml
+++ b/packages/FusedLocation/res/values-fr-rCA/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="5379477904423203699">"Fused Location"</string>
+ <string name="app_label" msgid="5379477904423203699">"Tables de fusion"</string>
</resources>
diff --git a/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm b/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm
new file mode 100644
index 0000000..2a95cfe
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_arabic.kcm
@@ -0,0 +1,319 @@
+# Copyright (C) 2013 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.
+
+#
+# Arabic (US-101 keys) keyboard layout.
+#
+
+type OVERLAY
+
+### ROW 1
+
+key GRAVE {
+ label: '`'
+ base, capslock: '\u0630'
+ shift: '\u0651'
+}
+
+key 1 {
+ label: '1'
+ base: '\u0661'
+ shift: '!'
+ capslock: '1'
+}
+
+key 2 {
+ label: '2'
+ base: '\u0662'
+ shift: '@'
+ capslock: '2'
+}
+
+key 3 {
+ label: '3'
+ base: '\u0663'
+ shift: '#'
+ capslock: '3'
+}
+
+key 4 {
+ label: '4'
+ base: '\u0664'
+ shift: '$'
+ capslock: '4'
+}
+
+key 5 {
+ label: '5'
+ base: '\u0665'
+ shift: '%'
+ capslock: '5'
+}
+
+key 6 {
+ label: '6'
+ base: '\u0666'
+ shift: '^'
+ capslock: '6'
+}
+
+key 7 {
+ label: '7'
+ base: '\u0667'
+ shift: '&'
+ capslock: '7'
+}
+
+key 8 {
+ label: '8'
+ base: '\u0668'
+ shift: '*'
+ capslock: '8'
+}
+
+key 9 {
+ label: '9'
+ base: '\u0669'
+ shift: '('
+ capslock: '9'
+}
+
+key 0 {
+ label: '0'
+ base: '\u0660'
+ shift: ')'
+ capslock: '0'
+}
+
+key MINUS {
+ label: '-'
+ base, capslock: '-'
+ shift: '_'
+}
+
+key EQUALS {
+ label: '='
+ base, capslock: '='
+ shift: '+'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base, capslock: '\u0636'
+ shift: '\u064e'
+}
+
+key W {
+ label: 'W'
+ base, capslock: '\u0635'
+ shift: '\u064b'
+}
+
+key E {
+ label: 'E'
+ base, capslock: '\u062b'
+ shift: '\u064f'
+}
+
+key R {
+ label: 'R'
+ base, capslock: '\u0642'
+ shift: '\u064c'
+}
+
+key T {
+ label: 'T'
+ base, capslock: '\u0641'
+ shift: '\ufef9'
+}
+
+key Y {
+ label: 'Y'
+ base, capslock: '\u063a'
+ shift: '\u0625'
+}
+
+key U {
+ label: 'U'
+ base, capslock: '\u0639'
+ shift: '\u2018'
+}
+
+key I {
+ label: 'I'
+ base, capslock: '\u0647'
+ shift: '\u00f7'
+}
+
+key O {
+ label: 'O'
+ base, capslock: '\u062e'
+ shift: '\u00d7'
+}
+
+key P {
+ label: 'P'
+ base, capslock: '\u062d'
+ shift: '\u061b'
+}
+
+key LEFT_BRACKET {
+ label: '['
+ base, capslock: '\u062c'
+ shift: '<'
+}
+
+key RIGHT_BRACKET {
+ label: ']'
+ base, capslock: '\u062f'
+ shift: '>'
+}
+
+key BACKSLASH {
+ label: '\\'
+ base, capslock: '\\'
+ shift: '|'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base, capslock: '\u0634'
+ shift: '\u0650'
+}
+
+key S {
+ label: 'S'
+ base, capslock: '\u0633'
+ shift: '\u064d'
+}
+
+key D {
+ label: 'D'
+ base, capslock: '\u064a'
+ shift: ']'
+}
+
+key F {
+ label: 'F'
+ base, capslock: '\u0628'
+ shift: '['
+}
+
+key G {
+ label: 'G'
+ base, capslock: '\u0644'
+ shift: '\ufef7'
+}
+
+key H {
+ label: 'H'
+ base, capslock: '\u0627'
+ shift: '\u0623'
+}
+
+key J {
+ label: 'J'
+ base, capslock: '\u062a'
+ shift: '\u0640'
+}
+
+key K {
+ label: 'K'
+ base, capslock: '\u0646'
+ shift: '\u060c'
+}
+
+key L {
+ label: 'L'
+ base, capslock: '\u0645'
+ shift: '/'
+}
+
+key SEMICOLON {
+ label: ';'
+ base, capslock: '\u0643'
+ shift: ':'
+}
+
+key APOSTROPHE {
+ label: '\''
+ base, capslock: '\u0637'
+ shift: '"'
+}
+
+### ROW 4
+
+key Z {
+ label: 'Z'
+ base, capslock: '\u0626'
+ shift: '~'
+}
+
+key X {
+ label: 'X'
+ base, capslock: '\u0621'
+ shift: '\u0652'
+}
+
+key C {
+ label: 'C'
+ base, capslock: '\u0624'
+ shift: '}'
+}
+
+key V {
+ label: 'V'
+ base, capslock: '\u0631'
+ shift: '{'
+}
+
+key B {
+ label: 'B'
+ base, capslock: '\ufefb'
+ shift: '\ufef5'
+}
+
+key N {
+ label: 'N'
+ base, capslock: '\u0649'
+ shift: '\u0622'
+}
+
+key M {
+ label: 'M'
+ base, capslock: '\u0629'
+ shift: '\u2019'
+}
+
+key COMMA {
+ label: ','
+ base, capslock: '\u0648'
+ shift: ','
+}
+
+key PERIOD {
+ label: '.'
+ base, capslock: '\u0632'
+ shift: '.'
+}
+
+key SLASH {
+ label: '/'
+ base, capslock: '\u0638'
+ shift: '\u061f'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_greek.kcm b/packages/InputDevices/res/raw/keyboard_layout_greek.kcm
new file mode 100644
index 0000000..a7684e1
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_greek.kcm
@@ -0,0 +1,338 @@
+# Copyright (C) 2013 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.
+
+#
+# Greek (EU based) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '`'
+ base, capslock: '`'
+ shift: '~'
+}
+
+key 1 {
+ label: '1'
+ base, capslock: '1'
+ shift: '!'
+}
+
+key 2 {
+ label: '2'
+ base, capslock: '2'
+ shift: '@'
+ ralt: '\u00b2'
+}
+
+key 3 {
+ label: '3'
+ base, capslock: '3'
+ shift: '#'
+ ralt: '\u00b3'
+}
+
+key 4 {
+ label: '4'
+ base, capslock: '4'
+ shift: '$'
+ ralt: '\u00a3'
+}
+
+key 5 {
+ label: '5'
+ base, capslock: '5'
+ shift: '%'
+ ralt: '\u00a7'
+}
+
+key 6 {
+ label: '6'
+ base, capslock: '6'
+ shift: '^'
+ ralt: '\u00b6'
+}
+
+key 7 {
+ label: '7'
+ base, capslock: '7'
+ shift: '&'
+}
+
+key 8 {
+ label: '8'
+ base, capslock: '8'
+ shift: '*'
+ ralt: '\u00a4'
+}
+
+key 9 {
+ label: '9'
+ base, capslock: '9'
+ shift: '('
+ ralt: '\u00a6'
+}
+
+key 0 {
+ label: '0'
+ base, capslock: '0'
+ shift: ')'
+ ralt: '\u00b0'
+}
+
+key MINUS {
+ label: '-'
+ base, capslock: '-'
+ shift: '_'
+ ralt: '\u00b1'
+}
+
+key EQUALS {
+ label: '='
+ base, capslock: '='
+ shift: '+'
+ ralt: '\u00bd'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base, capslock: ';'
+ shift: ':'
+}
+
+key W {
+ label: 'W'
+ base, capslock: '\u03c2'
+ shift: '\u0385'
+}
+
+key E {
+ label: 'E'
+ base: '\u03b5'
+ shift, capslock: '\u0395'
+ ralt: '\u20ac'
+}
+
+key R {
+ label: 'R'
+ base: '\u03c1'
+ shift, capslock: '\u03a1'
+ ralt: '\u00ae'
+}
+
+key T {
+ label: 'T'
+ base: '\u03c4'
+ shift, capslock: '\u03a4'
+}
+
+key Y {
+ label: 'Y'
+ base: '\u03c5'
+ shift, capslock: '\u03a5'
+ ralt: '\u00a5'
+}
+
+key U {
+ label: 'U'
+ base: '\u03b8'
+ shift, capslock: '\u0398'
+}
+
+key I {
+ label: 'I'
+ base: '\u03b9'
+ shift, capslock: '\u0399'
+}
+
+key O {
+ label: 'O'
+ base: '\u03bf'
+ shift, capslock: '\u039f'
+}
+
+key P {
+ label: 'P'
+ base: '\u03c0'
+ shift, capslock: '\u03a0'
+}
+
+key LEFT_BRACKET {
+ label: '['
+ base, capslock: '['
+ shift: '{'
+ ralt: '\u00ab'
+}
+
+key RIGHT_BRACKET {
+ label: ']'
+ base, capslock: ']'
+ shift: '}'
+ ralt: '\u00bb'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: '\u03b1'
+ shift, capslock: '\u0391'
+}
+
+key S {
+ label: 'S'
+ base: '\u03c3'
+ shift, capslock: '\u03a3'
+}
+
+key D {
+ label: 'D'
+ base: '\u03b4'
+ shift, capslock: '\u0394'
+}
+
+key F {
+ label: 'F'
+ base: '\u03c6'
+ shift, capslock: '\u03a6'
+}
+
+key G {
+ label: 'G'
+ base: '\u03b3'
+ shift, capslock: '\u0393'
+}
+
+key H {
+ label: 'H'
+ base: '\u03b7'
+ shift, capslock: '\u0397'
+}
+
+key J {
+ label: 'J'
+ base: '\u03be'
+ shift, capslock: '\u039e'
+}
+
+key K {
+ label: 'K'
+ base: '\u03ba'
+ shift, capslock: '\u039a'
+}
+
+key L {
+ label: 'L'
+ base: '\u03bb'
+ shift, capslock: '\u039b'
+}
+
+key SEMICOLON {
+ label: ';'
+ base, capslock: '\u0301'
+#should be \u0384 (greek tonos)
+ shift: '\u0308'
+ ralt: '\u0385'
+}
+
+key APOSTROPHE {
+ label: '\''
+ base, capslock: '\''
+ shift: '"'
+}
+
+key BACKSLASH {
+ label: '\\'
+ base, capslock: '\\'
+ shift: '|'
+ ralt: '\u00ac'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '<'
+ base, capslock: '<'
+ shift: '>'
+ ralt: '\\'
+ shift+ralt: '|'
+}
+
+key Z {
+ label: 'Z'
+ base: '\u03b6'
+ shift, capslock: '\u0396'
+}
+
+key X {
+ label: 'X'
+ base: '\u03c7'
+ shift, capslock: '\u03a7'
+}
+
+key C {
+ label: 'C'
+ base: '\u03c8'
+ shift, capslock: '\u03a8'
+ ralt: '\u00a9'
+}
+
+key V {
+ label: 'V'
+ base: '\u03c9'
+ shift, capslock: '\u03a9'
+}
+
+key B {
+ label: 'B'
+ base: '\u03b2'
+ shift, capslock: '\u0392'
+}
+
+key N {
+ label: 'N'
+ base: '\u03bd'
+ shift, capslock: '\u039d'
+}
+
+key M {
+ label: 'M'
+ base: '\u03bc'
+ shift, capslock: '\u039c'
+}
+
+key COMMA {
+ label: ','
+ base, capslock: ','
+ shift: '<'
+}
+
+key PERIOD {
+ label: '.'
+ base, capslock: '.'
+ shift: '>'
+}
+
+key SLASH {
+ label: '/'
+ base, capslock: '/'
+ shift: '?'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm b/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm
new file mode 100644
index 0000000..cd3a4b9
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_hebrew.kcm
@@ -0,0 +1,341 @@
+# Copyright (C) 2013 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.
+
+#
+# Hebrew (based EU) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '`'
+ base: ';'
+ shift: '~'
+ shift+capslock: '\u05b0'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+ shift+capslock: '\u05b1'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '@'
+ shift+capslock: '\u05b2'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '#'
+ shift+capslock: '\u05b3'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '$'
+ ralt: '\u20aa'
+ shift+capslock: '\u05b4'
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+ shift+capslock: '\u05b5'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '^'
+ shift+capslock: '\u05b6'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '&'
+ shift+capslock: '\u05b7'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '*'
+ shift+capslock: '\u05b8'
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: '('
+ shift+capslock: '\u05c2'
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: ')'
+ shift+capslock: '\u05c1'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+ ralt: '\u05bf'
+ shift+capslock: '\u05b9'
+}
+
+key EQUALS {
+ label: '='
+ base: '='
+ shift: '+'
+ shift+capslock: '\u05bc'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: '/'
+ shift, capslock: 'Q'
+}
+
+key W {
+ label: 'W'
+ base: '\u0027'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base: '\u05e7'
+ shift, capslock: 'E'
+ ralt: '\u20ac'
+}
+
+key R {
+ label: 'R'
+ base: '\u05e8'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: '\u05d0'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base: '\u05d8'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base: '\u05d5'
+ shift, capslock: 'U'
+ ralt: '\u05f0'
+}
+
+key I {
+ label: 'I'
+ base: '\u05df'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: '\u05dd'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: '\u05e4'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '['
+ base, capslock: '['
+ shift: '{'
+}
+
+key RIGHT_BRACKET {
+ label: ']'
+ base, capslock: ']'
+ shift: '}'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: '\u05e9'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base: '\u05d3'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: '\u05d2'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: '\u05db'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: '\u05e2'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: '\u05d9'
+ shift, capslock: 'H'
+ ralt: '\u05f2'
+}
+
+key J {
+ label: 'J'
+ base: '\u05d7'
+ shift, capslock: 'J'
+ ralt: '\u05f1'
+}
+
+key K {
+ label: 'K'
+ base: '\u05dc'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: '\u05da'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: ';'
+ base: '\u05e3'
+ shift: ':'
+ capslock: ';'
+}
+
+key APOSTROPHE {
+ label: '\''
+ base: ','
+ shift: '"'
+ capslock: '\''
+}
+
+key BACKSLASH {
+ label: '\\'
+ base: '\\'
+ shift: '|'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '\\'
+ base, capslock: '\\'
+ shift: '|'
+}
+
+key Z {
+ label: 'Z'
+ base: '\u05d6'
+ shift, capslock: 'Z'
+}
+
+key X {
+ label: 'X'
+ base: '\u05e1'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: '\u05d1'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: '\u05d4'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: '\u05e0'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: '\u05de'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base: '\u05e6'
+ shift, capslock: 'M'
+}
+
+key COMMA {
+ label: ','
+ base: '\u05ea'
+ shift: '<'
+ capslock: ','
+}
+
+key PERIOD {
+ label: '.'
+ base: '\u05e5'
+ shift: '>'
+ capslock: '.'
+}
+
+key SLASH {
+ label: '/'
+ base: '.'
+ shift: '?'
+ capslock: '/'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_lithuanian.kcm b/packages/InputDevices/res/raw/keyboard_layout_lithuanian.kcm
new file mode 100644
index 0000000..72ca333
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_lithuanian.kcm
@@ -0,0 +1,338 @@
+# Copyright (C) 2013 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.
+
+#
+# Lithuanian (EU based) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '`'
+ base: '`'
+ shift: '~'
+}
+
+key 1 {
+ label: '1'
+ base: '\u0105'
+ shift, capslock: '\u0104'
+ ralt: '1'
+ shift+ralt: '!'
+}
+
+key 2 {
+ label: '2'
+ base: '\u010d'
+ shift, capslock: '\u010c'
+ ralt: '2'
+ shift+ralt: '@'
+}
+
+key 3 {
+ label: '3'
+ base: '\u0119'
+ shift, capslock: '\u0118'
+ ralt: '3'
+ shift+ralt: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '\u0117'
+ shift, capslock: '\u0116'
+ ralt: '4'
+ shift+ralt: '$'
+}
+
+key 5 {
+ label: '5'
+ base: '\u012f'
+ shift, capslock: '\u012e'
+ ralt: '5'
+ shift+ralt: '%'
+}
+
+key 6 {
+ label: '6'
+ base: '\u0161'
+ shift, capslock: '\u0160'
+ ralt: '6'
+ shift+ralt: '\u0302'
+}
+
+key 7 {
+ label: '7'
+ base: '\u0173'
+ shift, capslock: '\u0172'
+ ralt: '7'
+ shift+ralt: '&'
+}
+
+key 8 {
+ label: '8'
+ base: '\u016b'
+ shift, capslock: '\u016a'
+ ralt: '8'
+ shift+ralt: '*'
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: '('
+ ralt: '9'
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: ')'
+ ralt: '0'
+}
+
+key MINUS {
+ label: '-'
+ base: '-'
+ shift: '_'
+}
+
+key EQUALS {
+ label: '='
+ base: '\u017e'
+ shift, capslock: '\u017d'
+ ralt: '='
+ shift+ralt: '+'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+ ralt: '\u20ac'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '['
+ base: '['
+ shift: '{'
+}
+
+key RIGHT_BRACKET {
+ label: ']'
+ base: ']'
+ shift: '}'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: ';'
+ base: ';'
+ shift: ':'
+}
+
+key APOSTROPHE {
+ label: '\''
+ base: '\''
+ shift: '"'
+}
+
+key BACKSLASH {
+ label: '\\'
+ base: '\\'
+ shift: '|'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '\\'
+ base: '\\'
+ shift: '|'
+}
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: '<'
+}
+
+key PERIOD {
+ label: '.'
+ base: '.'
+ shift: '>'
+}
+
+key SLASH {
+ label: '/'
+ base: '/'
+ shift: '?'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_spanish_latin.kcm b/packages/InputDevices/res/raw/keyboard_layout_spanish_latin.kcm
new file mode 100644
index 0000000..16eb53f
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_spanish_latin.kcm
@@ -0,0 +1,325 @@
+# Copyright (C) 2013 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.
+
+#
+# Spanish (Latin) (EU based) keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+ label: '|'
+ base: '|'
+ shift: '\u00ba'
+ ralt: '\u00ac'
+}
+
+key 1 {
+ label: '1'
+ base: '1'
+ shift: '!'
+}
+
+key 2 {
+ label: '2'
+ base: '2'
+ shift: '"'
+}
+
+key 3 {
+ label: '3'
+ base: '3'
+ shift: '#'
+}
+
+key 4 {
+ label: '4'
+ base: '4'
+ shift: '$'
+
+}
+
+key 5 {
+ label: '5'
+ base: '5'
+ shift: '%'
+}
+
+key 6 {
+ label: '6'
+ base: '6'
+ shift: '&'
+}
+
+key 7 {
+ label: '7'
+ base: '7'
+ shift: '/'
+}
+
+key 8 {
+ label: '8'
+ base: '8'
+ shift: '('
+}
+
+key 9 {
+ label: '9'
+ base: '9'
+ shift: ')'
+}
+
+key 0 {
+ label: '0'
+ base: '0'
+ shift: '='
+}
+
+key MINUS {
+ label: '\''
+ base: '\''
+ shift: '?'
+ ralt: '\\'
+}
+
+key EQUALS {
+ label: '\u00bf'
+ base: '\u00bf'
+ shift: '\u00a1'
+}
+
+### ROW 2
+
+key Q {
+ label: 'Q'
+ base: 'q'
+ shift, capslock: 'Q'
+ ralt: '@'
+}
+
+key W {
+ label: 'W'
+ base: 'w'
+ shift, capslock: 'W'
+}
+
+key E {
+ label: 'E'
+ base: 'e'
+ shift, capslock: 'E'
+}
+
+key R {
+ label: 'R'
+ base: 'r'
+ shift, capslock: 'R'
+}
+
+key T {
+ label: 'T'
+ base: 't'
+ shift, capslock: 'T'
+}
+
+key Y {
+ label: 'Y'
+ base: 'y'
+ shift, capslock: 'Y'
+}
+
+key U {
+ label: 'U'
+ base: 'u'
+ shift, capslock: 'U'
+}
+
+key I {
+ label: 'I'
+ base: 'i'
+ shift, capslock: 'I'
+}
+
+key O {
+ label: 'O'
+ base: 'o'
+ shift, capslock: 'O'
+}
+
+key P {
+ label: 'P'
+ base: 'p'
+ shift, capslock: 'P'
+}
+
+key LEFT_BRACKET {
+ label: '\u00b4'
+ base: '\u0301'
+ shift: '\u0308'
+ ralt: '['
+}
+
+key RIGHT_BRACKET {
+ label: '+'
+ base: '+'
+ shift: '*'
+ ralt: '\u0303'
+}
+
+### ROW 3
+
+key A {
+ label: 'A'
+ base: 'a'
+ shift, capslock: 'A'
+}
+
+key S {
+ label: 'S'
+ base: 's'
+ shift, capslock: 'S'
+}
+
+key D {
+ label: 'D'
+ base: 'd'
+ shift, capslock: 'D'
+}
+
+key F {
+ label: 'F'
+ base: 'f'
+ shift, capslock: 'F'
+}
+
+key G {
+ label: 'G'
+ base: 'g'
+ shift, capslock: 'G'
+}
+
+key H {
+ label: 'H'
+ base: 'h'
+ shift, capslock: 'H'
+}
+
+key J {
+ label: 'J'
+ base: 'j'
+ shift, capslock: 'J'
+}
+
+key K {
+ label: 'K'
+ base: 'k'
+ shift, capslock: 'K'
+}
+
+key L {
+ label: 'L'
+ base: 'l'
+ shift, capslock: 'L'
+}
+
+key SEMICOLON {
+ label: '\u00d1'
+ base: '\u00f1'
+ shift, capslock: '\u00d1'
+}
+
+key APOSTROPHE {
+ label: '{'
+ base: '{'
+ shift: '['
+ ralt: '\u0302'
+}
+
+key BACKSLASH {
+ label: '}'
+ base: '}'
+ shift: ']'
+ ralt: '\u0300'
+}
+
+### ROW 4
+
+key PLUS {
+ label: '<'
+ base: '<'
+ shift: '>'
+}
+
+key Z {
+ label: 'Z'
+ base: 'z'
+ shift, capslock: 'Z'
+}
+
+key X {
+ label: 'X'
+ base: 'x'
+ shift, capslock: 'X'
+}
+
+key C {
+ label: 'C'
+ base: 'c'
+ shift, capslock: 'C'
+}
+
+key V {
+ label: 'V'
+ base: 'v'
+ shift, capslock: 'V'
+}
+
+key B {
+ label: 'B'
+ base: 'b'
+ shift, capslock: 'B'
+}
+
+key N {
+ label: 'N'
+ base: 'n'
+ shift, capslock: 'N'
+}
+
+key M {
+ label: 'M'
+ base: 'm'
+ shift, capslock: 'M'
+}
+
+key COMMA {
+ label: ','
+ base: ','
+ shift: ';'
+}
+
+key PERIOD {
+ label: '.'
+ base: '.'
+ shift: ':'
+}
+
+key SLASH {
+ label: '-'
+ base: '-'
+ shift: '_'
+}
diff --git a/packages/InputDevices/res/values-af/strings.xml b/packages/InputDevices/res/values-af/strings.xml
index 13fcbb4..ddaf706 100644
--- a/packages/InputDevices/res/values-af/strings.xml
+++ b/packages/InputDevices/res/values-af/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Sloweens"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turks"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Oekraïens"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabies"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grieks"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebreeus"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litaus"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spaans (Latyn)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-am/strings.xml b/packages/InputDevices/res/values-am/strings.xml
index d475772..09b65e0 100644
--- a/packages/InputDevices/res/values-am/strings.xml
+++ b/packages/InputDevices/res/values-am/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"ስሎቫኒያ"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"ቱርክኛ"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ዩክሬን"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"አረብኛ"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"ግሪክኛ"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"ዕብራስጥ"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ሊቱዌኒያኛ"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ስፓኒሽ (ላቲን)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ar/strings.xml b/packages/InputDevices/res/values-ar/strings.xml
index 903d978..4c5cccc 100644
--- a/packages/InputDevices/res/values-ar/strings.xml
+++ b/packages/InputDevices/res/values-ar/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"السلوفينية"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"التركية"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"الأوكرانية"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"العربية"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"اليونانية"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"العبرية"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"الليتوانية"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"الإسبانية (اللاتينية)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-bg/strings.xml b/packages/InputDevices/res/values-bg/strings.xml
index 0c413a4..cc3eb36 100644
--- a/packages/InputDevices/res/values-bg/strings.xml
+++ b/packages/InputDevices/res/values-bg/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"словенски"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"турски"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"украински"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Арабска клавиатурна подредба"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Гръцка клавиатурна подредба"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Ивритска клавиатурна подредба"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литовска клавиатурна подредба"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Исп. клав. подредба (Лат. Америка)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ca/strings.xml b/packages/InputDevices/res/values-ca/strings.xml
index 2021b8f..2c8521c 100644
--- a/packages/InputDevices/res/values-ca/strings.xml
+++ b/packages/InputDevices/res/values-ca/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Eslovè"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turc"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraïnès"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Àrab"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grec"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebreu"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituà"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espanyol (llatí)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-cs/strings.xml b/packages/InputDevices/res/values-cs/strings.xml
index 33b420e..9b65eed 100644
--- a/packages/InputDevices/res/values-cs/strings.xml
+++ b/packages/InputDevices/res/values-cs/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"slovinské"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"turecké"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukrajinské"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"arabština"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"řečtina"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"hebrejština"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litevština"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"španělština (Latinská Amerika)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-da/strings.xml b/packages/InputDevices/res/values-da/strings.xml
index fc07db2..8b157b4 100644
--- a/packages/InputDevices/res/values-da/strings.xml
+++ b/packages/InputDevices/res/values-da/strings.xml
@@ -34,4 +34,14 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovensk"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Tyrkisk"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainsk"</string>
+ <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-de/strings.xml b/packages/InputDevices/res/values-de/strings.xml
index b5c3b50..b5a5870 100644
--- a/packages/InputDevices/res/values-de/strings.xml
+++ b/packages/InputDevices/res/values-de/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slowenisch"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Türkisch"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainisch"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabisch"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Griechisch"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebräisch"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litauisch"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanisch (Lateinisch)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-el/strings.xml b/packages/InputDevices/res/values-el/strings.xml
index f5d57a0..976f370 100644
--- a/packages/InputDevices/res/values-el/strings.xml
+++ b/packages/InputDevices/res/values-el/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Σλοβενικά"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Τουρκικά"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ουκρανικά"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Αραβικά"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Ελληνικά"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Εβραϊκά"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Λιθουανικά"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Ισπανικά (Λατινικής Αμερικής)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-en-rGB/strings.xml b/packages/InputDevices/res/values-en-rGB/strings.xml
index 2d794a6..50a98b26 100644
--- a/packages/InputDevices/res/values-en-rGB/strings.xml
+++ b/packages/InputDevices/res/values-en-rGB/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovenian"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turkish"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainian"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabic"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Greek"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebrew"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lithuanian"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-en-rIN/strings.xml b/packages/InputDevices/res/values-en-rIN/strings.xml
index 2d794a6..50a98b26 100644
--- a/packages/InputDevices/res/values-en-rIN/strings.xml
+++ b/packages/InputDevices/res/values-en-rIN/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovenian"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turkish"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainian"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabic"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Greek"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebrew"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lithuanian"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-es-rUS/strings.xml b/packages/InputDevices/res/values-es-rUS/strings.xml
index 2d61b80..b842a3b 100644
--- a/packages/InputDevices/res/values-es-rUS/strings.xml
+++ b/packages/InputDevices/res/values-es-rUS/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Esloveno"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turco"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraniano"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Árabe"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Griego"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebreo"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Español (latino)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-es/strings.xml b/packages/InputDevices/res/values-es/strings.xml
index 82ea4d6..8cb01c1 100644
--- a/packages/InputDevices/res/values-es/strings.xml
+++ b/packages/InputDevices/res/values-es/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Esloveno"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turco"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraniano"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Árabe"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Griego"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebreo"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Español (latino)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-et-rEE/strings.xml b/packages/InputDevices/res/values-et-rEE/strings.xml
index 5b4fa3b..4ffdb37 100644
--- a/packages/InputDevices/res/values-et-rEE/strings.xml
+++ b/packages/InputDevices/res/values-et-rEE/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Sloveenia"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Türgi"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukraina"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Araabia"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Kreeka"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Heebrea"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Leedu"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Hispaania (Ladina-Ameerika)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-fa/strings.xml b/packages/InputDevices/res/values-fa/strings.xml
index 06c7f3a..fd6f54b 100644
--- a/packages/InputDevices/res/values-fa/strings.xml
+++ b/packages/InputDevices/res/values-fa/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"اسلوونیایی"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"ترکی"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"اوکراینی"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"عربی"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"یونانی"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"عبری"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"لیتوانیایی"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"اسپانیایی (لاتین)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-fi/strings.xml b/packages/InputDevices/res/values-fi/strings.xml
index 428eb30..7e9b386 100644
--- a/packages/InputDevices/res/values-fi/strings.xml
+++ b/packages/InputDevices/res/values-fi/strings.xml
@@ -34,4 +34,14 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"sloveeni"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"turkki"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukraina"</string>
+ <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-fr-rCA/strings.xml b/packages/InputDevices/res/values-fr-rCA/strings.xml
index c947634..9000405 100644
--- a/packages/InputDevices/res/values-fr-rCA/strings.xml
+++ b/packages/InputDevices/res/values-fr-rCA/strings.xml
@@ -34,4 +34,14 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovène"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turc"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainien"</string>
+ <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-fr/strings.xml b/packages/InputDevices/res/values-fr/strings.xml
index 4ad4ffa..e3ca49c 100644
--- a/packages/InputDevices/res/values-fr/strings.xml
+++ b/packages/InputDevices/res/values-fr/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovène"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turc"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainien"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabe"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grec"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hébreu"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituanien"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espagnol (latin)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-hi/strings.xml b/packages/InputDevices/res/values-hi/strings.xml
index 8e1864e..a1a4ef2 100644
--- a/packages/InputDevices/res/values-hi/strings.xml
+++ b/packages/InputDevices/res/values-hi/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"स्लोवेनियाई"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"तुर्की"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"यूक्रेनियाई"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"अरबी"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"ग्रीक"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"हिब्रू"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"लिथुआनियाई"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"स्पेनिश (लैटिन)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-hr/strings.xml b/packages/InputDevices/res/values-hr/strings.xml
index 6217bf0..0f83293 100644
--- a/packages/InputDevices/res/values-hr/strings.xml
+++ b/packages/InputDevices/res/values-hr/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"slovenska"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"turska"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukrajinska"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arapski"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grčki"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebrejski"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litavski"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Španjolski (Latinska Amerika)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-hu/strings.xml b/packages/InputDevices/res/values-hu/strings.xml
index 0cdbfb2..645e597 100644
--- a/packages/InputDevices/res/values-hu/strings.xml
+++ b/packages/InputDevices/res/values-hu/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"szlovén"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"török"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukrán"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"arab"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"görög"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"héber"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litván"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"spanyol (latin-amerikai)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-hy-rAM/strings.xml b/packages/InputDevices/res/values-hy-rAM/strings.xml
index bc5bbfc..282dc82 100644
--- a/packages/InputDevices/res/values-hy-rAM/strings.xml
+++ b/packages/InputDevices/res/values-hy-rAM/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Սլովեներեն"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Թուրքերեն"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ուկրաիներեն"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Արաբերեն"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Հունարեն"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Եբրայերեն"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Լիտվերեն"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Իսպաներեն (Լատինական)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-in/strings.xml b/packages/InputDevices/res/values-in/strings.xml
index 11e2dd0a..a7fc330 100644
--- a/packages/InputDevices/res/values-in/strings.xml
+++ b/packages/InputDevices/res/values-in/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovenia"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turki"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukraina"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arab"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Yunani"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Ibrani"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lithuania"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanyol (Latin)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-it/strings.xml b/packages/InputDevices/res/values-it/strings.xml
index 334318e..e8fe310 100644
--- a/packages/InputDevices/res/values-it/strings.xml
+++ b/packages/InputDevices/res/values-it/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Sloveno"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turco"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraino"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabo"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Greco"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Ebraico"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spagnolo (America Latina)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-iw/strings.xml b/packages/InputDevices/res/values-iw/strings.xml
index a989391..d2673d9 100644
--- a/packages/InputDevices/res/values-iw/strings.xml
+++ b/packages/InputDevices/res/values-iw/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"סלובנית"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"טורקית"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"אוקראינית"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"ערבית"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"יוונית"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"עברית"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ליטאית"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ספרדית (לטינית)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ja/strings.xml b/packages/InputDevices/res/values-ja/strings.xml
index 950b727..86cd30e 100644
--- a/packages/InputDevices/res/values-ja/strings.xml
+++ b/packages/InputDevices/res/values-ja/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"スロベニア語"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"トルコ語"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ウクライナ語"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"アラビア語"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"ギリシャ語"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"ヘブライ語"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"リトアニア語"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"スペイン語(中南米)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ka-rGE/strings.xml b/packages/InputDevices/res/values-ka-rGE/strings.xml
index 6e507aa..14ebee8 100644
--- a/packages/InputDevices/res/values-ka-rGE/strings.xml
+++ b/packages/InputDevices/res/values-ka-rGE/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"სლოვენური"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"თურქული"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"უკრაინული"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"არაბული"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"ბერძნული"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"ებრაული"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ლიტვური"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ესპანური (ლათინური)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-km-rKH/strings.xml b/packages/InputDevices/res/values-km-rKH/strings.xml
index 9a8c99b..569f273 100644
--- a/packages/InputDevices/res/values-km-rKH/strings.xml
+++ b/packages/InputDevices/res/values-km-rKH/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"ស្លូវ៉ានី"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"ទួរគី"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"អ៊ុយក្រែន"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"អារ៉ាប់"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"ក្រិក"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"អ៊ីស្រាអែល"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"លីទុយអានី"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"អេស្ប៉ាញ (ឡាតាំង)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ko/strings.xml b/packages/InputDevices/res/values-ko/strings.xml
index 8071586..dbbe6ea 100644
--- a/packages/InputDevices/res/values-ko/strings.xml
+++ b/packages/InputDevices/res/values-ko/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"슬로베니아어"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"터키어"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"우크라이나어"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"아랍어"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"그리스어"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"히브리어"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"리투아니아어"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"스페인어(라틴)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-lo-rLA/strings.xml b/packages/InputDevices/res/values-lo-rLA/strings.xml
index 2c97e11..eaf5026 100644
--- a/packages/InputDevices/res/values-lo-rLA/strings.xml
+++ b/packages/InputDevices/res/values-lo-rLA/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"ສະໂລເວນຽນ"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"ເຕີກິສ"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ຢູເຄຣນຽນ"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"ອາຣັບ"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"ກຣີກ"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"ຮີບຣິວ"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ລິທົວນຽນ"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"ສະແປນນິດ (ລາຕິນ)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-lt/strings.xml b/packages/InputDevices/res/values-lt/strings.xml
index c0ed159..2fcacde 100644
--- a/packages/InputDevices/res/values-lt/strings.xml
+++ b/packages/InputDevices/res/values-lt/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovėnų k."</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turkų k."</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainiečių k."</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabų"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Graikų"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebrajų"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lietuvių"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Ispanų (Lotynų Amerika)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-lv/strings.xml b/packages/InputDevices/res/values-lv/strings.xml
index 07a8654..921c881 100644
--- a/packages/InputDevices/res/values-lv/strings.xml
+++ b/packages/InputDevices/res/values-lv/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovēņu"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turku"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukraiņu"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arābu"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grieķu"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Ivrits"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lietuviešu"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spāņu (latīņu)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-mn-rMN/strings.xml b/packages/InputDevices/res/values-mn-rMN/strings.xml
index ec6cccb..c99339e 100644
--- a/packages/InputDevices/res/values-mn-rMN/strings.xml
+++ b/packages/InputDevices/res/values-mn-rMN/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Словени"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Турк"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Украйн"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Араб"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Грек"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Еврей"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литви"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Испани (Латин)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ms-rMY/strings.xml b/packages/InputDevices/res/values-ms-rMY/strings.xml
index 486f048..b26a633 100644
--- a/packages/InputDevices/res/values-ms-rMY/strings.xml
+++ b/packages/InputDevices/res/values-ms-rMY/strings.xml
@@ -34,4 +34,14 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Bahasa Slovenia"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Bahasa Turki"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Bahasa Ukraine"</string>
+ <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-nb/strings.xml b/packages/InputDevices/res/values-nb/strings.xml
index b646061..e880981 100644
--- a/packages/InputDevices/res/values-nb/strings.xml
+++ b/packages/InputDevices/res/values-nb/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovensk"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Tyrkisk"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainsk"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabisk"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Gresk"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebraisk"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litauisk"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spansk (latinsk)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-nl/strings.xml b/packages/InputDevices/res/values-nl/strings.xml
index 56d84c9..92a9fcf 100644
--- a/packages/InputDevices/res/values-nl/strings.xml
+++ b/packages/InputDevices/res/values-nl/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Sloveens"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turks"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Oekraïens"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabisch"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grieks"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebreeuws"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litouws"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spaans (Latijns-Amerika)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-pl/strings.xml b/packages/InputDevices/res/values-pl/strings.xml
index 4522215..828a45f 100644
--- a/packages/InputDevices/res/values-pl/strings.xml
+++ b/packages/InputDevices/res/values-pl/strings.xml
@@ -34,4 +34,14 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Słoweński"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turecki"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukraiński"</string>
+ <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-pt-rPT/strings.xml b/packages/InputDevices/res/values-pt-rPT/strings.xml
index 9a639cd..670badd 100644
--- a/packages/InputDevices/res/values-pt-rPT/strings.xml
+++ b/packages/InputDevices/res/values-pt-rPT/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Esloveno"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turco"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraniano"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Árabe"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grego"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebraico"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espanhol (América Latina)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-pt/strings.xml b/packages/InputDevices/res/values-pt/strings.xml
index 05a0cd0..71274aa 100644
--- a/packages/InputDevices/res/values-pt/strings.xml
+++ b/packages/InputDevices/res/values-pt/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Esloveno"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turco"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraniano"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Árabe"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grego"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebraico"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lituano"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Espanhol (América Latina)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-ro/strings.xml b/packages/InputDevices/res/values-ro/strings.xml
index 895d8f6..c61455d 100644
--- a/packages/InputDevices/res/values-ro/strings.xml
+++ b/packages/InputDevices/res/values-ro/strings.xml
@@ -34,4 +34,14 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovenă"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turcă"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ucraineană"</string>
+ <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-ru/strings.xml b/packages/InputDevices/res/values-ru/strings.xml
index a4cbfd7..8b93723 100644
--- a/packages/InputDevices/res/values-ru/strings.xml
+++ b/packages/InputDevices/res/values-ru/strings.xml
@@ -34,4 +34,14 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"словенский"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"турецкий"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"украинский"</string>
+ <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-sk/strings.xml b/packages/InputDevices/res/values-sk/strings.xml
index 01ab042..ec511b3 100644
--- a/packages/InputDevices/res/values-sk/strings.xml
+++ b/packages/InputDevices/res/values-sk/strings.xml
@@ -34,4 +34,14 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"slovinské"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"turecké"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukrajinské"</string>
+ <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-sl/strings.xml b/packages/InputDevices/res/values-sl/strings.xml
index 30ff3c4..b8fc823e 100644
--- a/packages/InputDevices/res/values-sl/strings.xml
+++ b/packages/InputDevices/res/values-sl/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"slovenska"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"turška"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ukrajinska"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"arabščina"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"grščina"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"hebrejščina"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"litovščina"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"španščina (Latinska Amerika)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-sr/strings.xml b/packages/InputDevices/res/values-sr/strings.xml
index d23ac00..45e0b4b 100644
--- a/packages/InputDevices/res/values-sr/strings.xml
+++ b/packages/InputDevices/res/values-sr/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"словеначка"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"турска"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"украјинска"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"арапски"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"грчки"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"хебрејски"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"литвански"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"шпански (Латинска Америка)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-sv/strings.xml b/packages/InputDevices/res/values-sv/strings.xml
index 25a5ae8..ce20bff 100644
--- a/packages/InputDevices/res/values-sv/strings.xml
+++ b/packages/InputDevices/res/values-sv/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovenskt"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turkiskt"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainskt"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabiska"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Grekiska"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebreiska"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Litauiska"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanska (latinamerikansk)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-sw/strings.xml b/packages/InputDevices/res/values-sw/strings.xml
index 65ab96a1..38bc83a 100644
--- a/packages/InputDevices/res/values-sw/strings.xml
+++ b/packages/InputDevices/res/values-sw/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Kislovenia"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Kituruki"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Kiukrania"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Kiarabu"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Kigiriki"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Kiyahudi"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Kilithuania"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Kihispania (Kilatini)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-th/strings.xml b/packages/InputDevices/res/values-th/strings.xml
index 0cc7d47..8951281 100644
--- a/packages/InputDevices/res/values-th/strings.xml
+++ b/packages/InputDevices/res/values-th/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"สโลวีเนีย"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"ตุรกี"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"ยูเครน"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"ภาษาอารบิค"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"กรีก"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"ฮิบรู"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"ลิทัวเนีย"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"สเปน (ละติน)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-tl/strings.xml b/packages/InputDevices/res/values-tl/strings.xml
index 08f34d2..c551e20 100644
--- a/packages/InputDevices/res/values-tl/strings.xml
+++ b/packages/InputDevices/res/values-tl/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovenian"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Turkish"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukrainian"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Arabic"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Greek"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Hebrew"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Lithuanian"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Spanish (Latin)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-tr/strings.xml b/packages/InputDevices/res/values-tr/strings.xml
index f7c1262..df9a280 100644
--- a/packages/InputDevices/res/values-tr/strings.xml
+++ b/packages/InputDevices/res/values-tr/strings.xml
@@ -34,4 +34,14 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Slovence"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Türkçe"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Ukraynaca"</string>
+ <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-uk/strings.xml b/packages/InputDevices/res/values-uk/strings.xml
index ee6ffc7..b4b9923 100644
--- a/packages/InputDevices/res/values-uk/strings.xml
+++ b/packages/InputDevices/res/values-uk/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"словенська"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"турецька"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"українська"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Арабська"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Грецька"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Іврит"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Литовська"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Іспанська (латиниця)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-vi/strings.xml b/packages/InputDevices/res/values-vi/strings.xml
index 7a65e45..18aa989 100644
--- a/packages/InputDevices/res/values-vi/strings.xml
+++ b/packages/InputDevices/res/values-vi/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Tiếng Sloven"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Tiếng Thổ Nhĩ Kỳ"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Tiếng Ukraina"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"Tiếng Ả rập"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Tiếng Hy Lạp"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Tiếng Do Thái"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Tiếng Lithuania"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Tiếng Tây Ban Nha (La tinh)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-zh-rCN/strings.xml b/packages/InputDevices/res/values-zh-rCN/strings.xml
index 85b1c84..e055ce2 100644
--- a/packages/InputDevices/res/values-zh-rCN/strings.xml
+++ b/packages/InputDevices/res/values-zh-rCN/strings.xml
@@ -34,4 +34,14 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"斯洛文尼亚语"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"土耳其语"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"乌克兰语"</string>
+ <!-- no translation found for keyboard_layout_arabic (5671970465174968712) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_greek (7289253560162386040) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_hebrew (7241473985890173812) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_lithuanian (6943110873053106534) -->
+ <skip />
+ <!-- no translation found for keyboard_layout_spanish_latin (5690539836069535697) -->
+ <skip />
</resources>
diff --git a/packages/InputDevices/res/values-zh-rHK/strings.xml b/packages/InputDevices/res/values-zh-rHK/strings.xml
index 839c546..031f294 100644
--- a/packages/InputDevices/res/values-zh-rHK/strings.xml
+++ b/packages/InputDevices/res/values-zh-rHK/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"斯洛文尼亞文"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"土耳其文"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"烏克蘭文"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"阿拉伯文"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"希臘文"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"希伯來文"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"立陶宛文"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"西班牙文 (拉丁美洲)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-zh-rTW/strings.xml b/packages/InputDevices/res/values-zh-rTW/strings.xml
index ba9f132..76cb6a2 100644
--- a/packages/InputDevices/res/values-zh-rTW/strings.xml
+++ b/packages/InputDevices/res/values-zh-rTW/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"斯洛維尼亞文"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"土耳其文"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"烏克蘭文"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"阿拉伯文"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"希臘文"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"希伯來文"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"立陶宛文"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"西班牙文 (拉丁美洲)"</string>
</resources>
diff --git a/packages/InputDevices/res/values-zu/strings.xml b/packages/InputDevices/res/values-zu/strings.xml
index fbf1074..2cdfe52 100644
--- a/packages/InputDevices/res/values-zu/strings.xml
+++ b/packages/InputDevices/res/values-zu/strings.xml
@@ -34,4 +34,9 @@
<string name="keyboard_layout_slovenian" msgid="1735933028924982368">"Isi-Slovenian"</string>
<string name="keyboard_layout_turkish" msgid="7736163250907964898">"Isi-Turkish"</string>
<string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"Isi-Ukrainian"</string>
+ <string name="keyboard_layout_arabic" msgid="5671970465174968712">"I-Arabhu"</string>
+ <string name="keyboard_layout_greek" msgid="7289253560162386040">"Isi-Greek"</string>
+ <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Isi-Hebrew"</string>
+ <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Isi-Lithuanian"</string>
+ <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Isi-Spanish (Latin)"</string>
</resources>
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 54c18f1..6239336 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -98,4 +98,19 @@
<!-- Ukrainian keyboard layout label. [CHAR LIMIT=35] -->
<string name="keyboard_layout_ukrainian">Ukrainian</string>
+
+ <!-- Arabic keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_arabic">Arabic</string>
+
+ <!-- Greek keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_greek">Greek</string>
+
+ <!-- Hebrew keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_hebrew">Hebrew</string>
+
+ <!-- Lithuanian keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_lithuanian">Lithuanian</string>
+
+ <!-- Spanish (Latin) keyboard layout label. [CHAR LIMIT=35] -->
+ <string name="keyboard_layout_spanish_latin">Spanish (Latin)</string>
</resources>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index 1f48a36..dc1db0b 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -123,4 +123,24 @@
<keyboard-layout android:name="keyboard_layout_ukrainian"
android:label="@string/keyboard_layout_ukrainian"
android:keyboardLayout="@raw/keyboard_layout_ukrainian" />
+
+ <keyboard-layout android:name="keyboard_layout_arabic"
+ android:label="@string/keyboard_layout_arabic"
+ android:keyboardLayout="@raw/keyboard_layout_arabic" />
+
+ <keyboard-layout android:name="keyboard_layout_greek"
+ android:label="@string/keyboard_layout_greek"
+ android:keyboardLayout="@raw/keyboard_layout_greek" />
+
+ <keyboard-layout android:name="keyboard_layout_hebrew"
+ android:label="@string/keyboard_layout_hebrew"
+ android:keyboardLayout="@raw/keyboard_layout_hebrew" />
+
+ <keyboard-layout android:name="keyboard_layout_lithuanian"
+ android:label="@string/keyboard_layout_lithuanian"
+ android:keyboardLayout="@raw/keyboard_layout_lithuanian" />
+
+ <keyboard-layout android:name="keyboard_layout_spanish_latin"
+ android:label="@string/keyboard_layout_spanish_latin"
+ android:keyboardLayout="@raw/keyboard_layout_spanish_latin" />
</keyboard-layouts>
diff --git a/packages/Keyguard/AndroidManifest.xml b/packages/Keyguard/AndroidManifest.xml
index 66d1e75..75b7dbd 100644
--- a/packages/Keyguard/AndroidManifest.xml
+++ b/packages/Keyguard/AndroidManifest.xml
@@ -39,11 +39,13 @@
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
<uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
+ <uses-permission android:name="android.permission.TRUST_LISTENER" />
<application android:label="@string/app_name"
android:process="com.android.systemui"
android:persistent="true"
- android:supportsRtl="true">
+ android:supportsRtl="true"
+ android:requiredForProfile="all">
<service android:name=".KeyguardService"
android:exported="true" />
diff --git a/packages/Keyguard/res/values-sk/strings.xml b/packages/Keyguard/res/values-sk/strings.xml
index cdf8ca9..89ac293 100644
--- a/packages/Keyguard/res/values-sk/strings.xml
+++ b/packages/Keyguard/res/values-sk/strings.xml
@@ -35,7 +35,7 @@
<string name="keyguard_low_battery" msgid="8143808018719173859">"Pripojte nabíjačku."</string>
<string name="keyguard_instructions_when_pattern_disabled" msgid="1332288268600329841">"Telefón odomknete stlačením tlačidla Menu."</string>
<string name="keyguard_network_locked_message" msgid="9169717779058037168">"Sieť je zablokovaná"</string>
- <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"Nie je vložená karta SIM."</string>
+ <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"Nie je vložená karta SIM"</string>
<string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"V tablete nie je žiadna karta SIM."</string>
<string name="keyguard_missing_sim_message" product="default" msgid="3481110395508637643">"V telefóne nie je žiadna karta SIM."</string>
<string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"Vložte kartu SIM."</string>
diff --git a/packages/Keyguard/res/values/styles.xml b/packages/Keyguard/res/values/styles.xml
index d4f98af..80fcf75 100644
--- a/packages/Keyguard/res/values/styles.xml
+++ b/packages/Keyguard/res/values/styles.xml
@@ -68,7 +68,7 @@
<item name="android:textSize">@dimen/widget_big_font_size</item>
</style>
- <style name="Widget.TransportControl.SeekBar" parent="@android:style/Widget.Holo.SeekBar">
+ <style name="Widget.TransportControl.SeekBar" parent="@android:style/Widget.DeviceDefault.Light.SeekBar">
<item name="android:indeterminateOnly">false</item>
<item name="android:progressDrawable">@drawable/scrubber_progress_horizontal_holo_light</item>
<item name="android:indeterminateDrawable">@drawable/scrubber_progress_horizontal_holo_light</item>
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java b/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
index 368a97a..0d5e477 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
@@ -104,9 +104,10 @@
// Workaround to avoid camera release/acquisition race when resuming face unlock
// after showing lockscreen camera (bug 11063890).
- KeyguardUpdateMonitor.getInstance(getContext()).setAlternateUnlockEnabled(false);
+ KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(getContext());
+ updateMonitor.setAlternateUnlockEnabled(false);
- if (lockPatternUtils.isSecure()) {
+ if (mustLaunchSecurely()) {
// Launch the secure version of the camera
if (wouldLaunchResolverActivity(SECURE_CAMERA_INTENT)) {
// TODO: Show disambiguation dialog instead.
@@ -123,6 +124,13 @@
}
}
+ private boolean mustLaunchSecurely() {
+ LockPatternUtils lockPatternUtils = getLockPatternUtils();
+ KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(getContext());
+ int currentUser = lockPatternUtils.getCurrentUser();
+ return lockPatternUtils.isSecure() && !updateMonitor.getUserHasTrust(currentUser);
+ }
+
public void launchWidgetPicker(int appWidgetId) {
Intent pickIntent = new Intent(AppWidgetManager.ACTION_KEYGUARD_APPWIDGET_PICK);
@@ -177,9 +185,9 @@
Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
- boolean isSecure = lockPatternUtils.isSecure();
- if (!isSecure || showsWhileLocked) {
- if (!isSecure) {
+ boolean mustLaunchSecurely = mustLaunchSecurely();
+ if (!mustLaunchSecurely || showsWhileLocked) {
+ if (!mustLaunchSecurely) {
dismissKeyguardOnNextActivity();
}
try {
@@ -253,7 +261,7 @@
}
private Intent getCameraIntent() {
- return getLockPatternUtils().isSecure() ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
+ return mustLaunchSecurely() ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
}
private boolean wouldLaunchResolverActivity(Intent intent) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
index 9f5768a..da6482a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -23,6 +23,7 @@
import com.android.internal.widget.LockPatternUtils;
public class KeyguardSecurityModel {
+
/**
* The different types of security available for {@link Mode#UnlockScreen}.
* @see com.android.internal.policy.impl.LockPatternKeyguardView#getUnlockMode()
@@ -82,6 +83,8 @@
} else if (simState == IccCardConstants.State.PUK_REQUIRED
&& mLockPatternUtils.isPukUnlockScreenEnable()) {
mode = SecurityMode.SimPuk;
+ } else if (updateMonitor.getUserHasTrust(mLockPatternUtils.getCurrentUser())) {
+ mode = SecurityMode.None;
} else {
final int security = mLockPatternUtils.getKeyguardStoredPasswordQuality();
switch (security) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 3b712e9..88c78ab 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -20,6 +20,7 @@
import android.app.IUserSwitchObserver;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
+import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -51,6 +52,8 @@
import android.telephony.TelephonyManager;
import android.util.Log;
+import android.util.SparseBooleanArray;
+
import com.google.android.collect.Lists;
import java.lang.ref.WeakReference;
@@ -66,7 +69,7 @@
* the device, and {@link #getFailedUnlockAttempts()}, {@link #reportFailedAttempt()}
* and {@link #clearFailedUnlockAttempts()}. Maybe we should rename this 'KeyguardContext'...
*/
-public class KeyguardUpdateMonitor {
+public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private static final String TAG = "KeyguardUpdateMonitor";
private static final boolean DEBUG = false;
@@ -205,6 +208,17 @@
private AudioManager mAudioManager;
+ private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
+
+ @Override
+ public void onTrustChanged(boolean enabled, int userId) {
+ mUserHasTrust.put(userId, enabled);
+ }
+
+ public boolean getUserHasTrust(int userId) {
+ return mUserHasTrust.get(userId);
+ }
+
static class DisplayClientState {
public int clientGeneration;
public boolean clearing;
@@ -581,6 +595,9 @@
// TODO Auto-generated catch block
e.printStackTrace();
}
+
+ TrustManager trustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
+ trustManager.registerTrustListener(this);
}
private boolean isDeviceProvisionedInSettingsDb() {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 481d132..556711b 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -178,4 +178,5 @@
* Called when the NFC Service has found a tag that is registered for NFC unlock.
*/
public void onNfcUnlock() { }
+
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
index 3fc562c..354d13f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
@@ -550,7 +550,9 @@
@Override
public int getSessionType() {
- return mLockPatternUtils.isSecure() ? Session.TYPE_KEYGUARD_SECURE
+ return mLockPatternUtils.isSecure() && !mUpdateMonitor.getUserHasTrust(
+ mLockPatternUtils.getCurrentUser())
+ ? Session.TYPE_KEYGUARD_SECURE
: Session.TYPE_KEYGUARD_INSECURE;
}
}, new File(mContext.getCacheDir(), "keyguard_analytics.bin"));
diff --git a/packages/Keyguard/test/AndroidManifest.xml b/packages/Keyguard/test/AndroidManifest.xml
index b801e4b..1638127 100644
--- a/packages/Keyguard/test/AndroidManifest.xml
+++ b/packages/Keyguard/test/AndroidManifest.xml
@@ -23,7 +23,7 @@
<application android:label="@string/app_name" android:icon="@drawable/app_icon">
<activity android:name=".KeyguardTestActivity"
android:label="@string/app_name"
- android:theme="@android:style/Theme.Holo">
+ android:theme="@android:style/Theme.DeviceDefault.Light">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
diff --git a/packages/Keyguard/test/SampleTrustAgent/Android.mk b/packages/Keyguard/test/SampleTrustAgent/Android.mk
new file mode 100644
index 0000000..7551fdf
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/Android.mk
@@ -0,0 +1,33 @@
+# 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := SampleTrustAgent
+
+# Remove these to verify permission checks are working correctly
+#LOCAL_CERTIFICATE := platform
+#LOCAL_PRIVILEGED_MODULE := true
+
+LOCAL_MODULE_TAGS := tests
+
+# LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
+
+include $(BUILD_PACKAGE)
diff --git a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
new file mode 100644
index 0000000..1511911
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2014 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.trustagent.test">
+ <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17"/>
+ <uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
+ <application android:label="@string/app_name">
+ <service
+ android:name=".SampleTrustAgent"
+ android:label="@string/app_name"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.service.trust.TrustAgentService" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <meta-data android:name="android.service.trust.trustagent"
+ android:resource="@xml/sample_trust_agent"/>
+ </service>
+
+ <activity
+ android:name=".SampleTrustAgentSettings"
+ android:label="@string/app_name"
+ android:exported="true"
+ android:launchMode="singleInstance" >
+ </activity>
+ </application>
+</manifest>
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml b/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
new file mode 100644
index 0000000..01b107b
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/res/layout/sample_trust_agent_settings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2014 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <Button android:id="@+id/enable_trust"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Grant trust for 30 seconds" />
+ <Button android:id="@+id/revoke_trust"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Revoke trust" />
+ <CheckBox android:id="@+id/report_unlock_attempts"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Report unlock attempts" />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/values/strings.xml b/packages/Keyguard/test/SampleTrustAgent/res/values/strings.xml
new file mode 100644
index 0000000..0c6b502
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2014 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<resources>
+ <string name="app_name">Sample Trust Agent</string>
+</resources>
\ No newline at end of file
diff --git a/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml b/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml
new file mode 100644
index 0000000..b48e011
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/res/xml/sample_trust_agent.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2014 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<trust_agent xmlns:android="http://schemas.android.com/apk/res/android"
+ android:settingsActivity=".SampleTrustAgentSettings" />
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
new file mode 100644
index 0000000..25406d6
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgent.java
@@ -0,0 +1,107 @@
+/*
+ * 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.trustagent.test;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.service.trust.TrustAgentService;
+import android.support.v4.content.LocalBroadcastManager;
+import android.widget.Toast;
+
+public class SampleTrustAgent extends TrustAgentService {
+
+ LocalBroadcastManager mLocalBroadcastManager;
+
+ private static final String ACTION_ENABLE_TRUST = "action.sample_trust_agent.enable_trust";
+ private static final String ACTION_REVOKE_TRUST = "action.sample_trust_agent.revoke_trust";
+
+ private static final String EXTRA_MESSAGE = "extra.message";
+ private static final String EXTRA_DURATION = "extra.duration";
+ private static final String EXTRA_EXTRA = "extra.extra";
+
+ private static final String PREFERENCE_REPORT_UNLOCK_ATTEMPTS
+ = "preference.report_unlock_attempts";
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(ACTION_ENABLE_TRUST);
+ filter.addAction(ACTION_REVOKE_TRUST);
+ mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
+ mLocalBroadcastManager.registerReceiver(mReceiver, filter);
+ }
+
+ @Override
+ protected void onUnlockAttempt(boolean successful) {
+ if (getReportUnlockAttempts(this)) {
+ Toast.makeText(this, "onUnlockAttempt(successful=" + successful + ")",
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mLocalBroadcastManager.unregisterReceiver(mReceiver);
+ }
+
+ private BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (ACTION_ENABLE_TRUST.equals(action)) {
+ enableTrust(intent.getStringExtra(EXTRA_MESSAGE),
+ intent.getLongExtra(EXTRA_DURATION, 0),
+ false /* initiatedByUser */);
+ } else if (ACTION_REVOKE_TRUST.equals(action)) {
+ revokeTrust();
+ }
+ }
+ };
+
+ public static void sendEnableTrust(Context context,
+ String message, long durationMs, Bundle extra) {
+ Intent intent = new Intent(ACTION_ENABLE_TRUST);
+ intent.putExtra(EXTRA_MESSAGE, message);
+ intent.putExtra(EXTRA_DURATION, durationMs);
+ intent.putExtra(EXTRA_EXTRA, extra);
+ LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
+ }
+
+ public static void sendRevokeTrust(Context context) {
+ Intent intent = new Intent(ACTION_REVOKE_TRUST);
+ LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
+ }
+
+ public static void setReportUnlockAttempts(Context context, boolean enabled) {
+ SharedPreferences sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(context);
+ sharedPreferences.edit().putBoolean(PREFERENCE_REPORT_UNLOCK_ATTEMPTS, enabled).apply();
+ }
+
+ public static boolean getReportUnlockAttempts(Context context) {
+ SharedPreferences sharedPreferences = PreferenceManager
+ .getDefaultSharedPreferences(context);
+ return sharedPreferences.getBoolean(PREFERENCE_REPORT_UNLOCK_ATTEMPTS, false);
+ }
+}
diff --git a/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
new file mode 100644
index 0000000..0a6f675
--- /dev/null
+++ b/packages/Keyguard/test/SampleTrustAgent/src/com/android/trustagent/test/SampleTrustAgentSettings.java
@@ -0,0 +1,69 @@
+/*
+ * 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.trustagent.test;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.os.Bundle;
+import android.preference.CheckBoxPreference;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+
+public class SampleTrustAgentSettings extends Activity implements View.OnClickListener,
+ CompoundButton.OnCheckedChangeListener {
+
+ private static final int TRUST_DURATION_MS = 30 * 1000;
+
+ private CheckBox mReportUnlockAttempts;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.sample_trust_agent_settings);
+
+ findViewById(R.id.enable_trust).setOnClickListener(this);
+ findViewById(R.id.revoke_trust).setOnClickListener(this);
+
+ mReportUnlockAttempts = (CheckBox) findViewById(R.id.report_unlock_attempts);
+ mReportUnlockAttempts.setOnCheckedChangeListener(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mReportUnlockAttempts.setChecked(SampleTrustAgent.getReportUnlockAttempts(this));
+ }
+
+ @Override
+ public void onClick(View v) {
+ int id = v.getId();
+ if (id == R.id.enable_trust) {
+ SampleTrustAgent.sendEnableTrust(this, "SampleTrustAgent", TRUST_DURATION_MS,
+ null /* extra */);
+ } else if (id == R.id.revoke_trust) {
+ SampleTrustAgent.sendRevokeTrust(this);
+ }
+ }
+
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (buttonView.getId() == R.id.report_unlock_attempts) {
+ SampleTrustAgent.setReportUnlockAttempts(this, isChecked);
+ }
+ }
+}
diff --git a/packages/PrintSpooler/res/layout/select_printer_activity.xml b/packages/PrintSpooler/res/layout/select_printer_activity.xml
index 6fc77df..4488b6a 100644
--- a/packages/PrintSpooler/res/layout/select_printer_activity.xml
+++ b/packages/PrintSpooler/res/layout/select_printer_activity.xml
@@ -61,7 +61,7 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:indeterminate="true"
- style="@android:style/Widget.Holo.ProgressBar.Horizontal">
+ style="@android:style/Widget.DeviceDefault.Light.ProgressBar.Horizontal">
</ProgressBar>
</LinearLayout>
diff --git a/packages/PrintSpooler/res/values-da/strings.xml b/packages/PrintSpooler/res/values-da/strings.xml
index 74190b4..1a871f8 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -69,8 +69,8 @@
<item msgid="2762241247228983754">"Farve"</item>
</string-array>
<string-array name="orientation_labels">
- <item msgid="4061931020926489228">"Portræt"</item>
- <item msgid="3199660090246166812">"Landskab"</item>
+ <item msgid="4061931020926489228">"Stående"</item>
+ <item msgid="3199660090246166812">"Liggende"</item>
</string-array>
<string-array name="page_options_labels">
<item msgid="7421377442011699994">"Alle"</item>
diff --git a/packages/PrintSpooler/res/values-sl/strings.xml b/packages/PrintSpooler/res/values-sl/strings.xml
index 5d4fe94..e299508 100644
--- a/packages/PrintSpooler/res/values-sl/strings.xml
+++ b/packages/PrintSpooler/res/values-sl/strings.xml
@@ -69,7 +69,7 @@
<item msgid="2762241247228983754">"Barvno"</item>
</string-array>
<string-array name="orientation_labels">
- <item msgid="4061931020926489228">"Navpično"</item>
+ <item msgid="4061931020926489228">"Pokončno"</item>
<item msgid="3199660090246166812">"Ležeče"</item>
</string-array>
<string-array name="page_options_labels">
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index 55c8687..a84e9b3 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -31,7 +31,7 @@
<string name="install_for_print_preview" msgid="6366303997385509332">"Sakinisha kitazamaji cha PDF kwa onyesho la kuchungulia"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"Programu ya kuchapisha imeacha kufanya kazi"</string>
<string name="page_count_unknown" msgid="6058852665954511124">"Kurasa"</string>
- <string name="generating_print_job" msgid="3119608742651698916">"Inazanzisha kazi ya kuchapisha"</string>
+ <string name="generating_print_job" msgid="3119608742651698916">"Inaleta kazi ya kuchapisha"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"Hifadhi kama PDF"</string>
<string name="all_printers" msgid="5018829726861876202">"Printa zote..."</string>
<string name="print_dialog" msgid="32628687461331979">"Chapisha mazungumzo"</string>
@@ -63,7 +63,7 @@
<string name="no_connection_to_printer" msgid="2159246915977282728">"Hakuna muunganisho kwa printa"</string>
<string name="reason_unknown" msgid="5507940196503246139">"haijulikani"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> - haipatikani"</string>
- <string name="print_error_default_message" msgid="8568506918983980567">"Haikuweza kuunda kazi ya kuchapisha"</string>
+ <string name="print_error_default_message" msgid="8568506918983980567">"Haikuweza kuleta kazi ya kuchapisha"</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"Nyeusi na Nyeupe"</item>
<item msgid="2762241247228983754">"Rangi"</item>
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index 86f4a37..94ab895 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -16,7 +16,7 @@
<resources>
- <style name="PrintJobConfigActivityTheme" parent="@android:style/Theme.Holo.Light.NoActionBar">
+ <style name="PrintJobConfigActivityTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowSoftInputMode">stateAlwaysHidden|adjustResize</item>
<item name="android:windowIsTranslucent">true</item>
@@ -25,11 +25,11 @@
<item name="android:windowIsFloating">true</item>
</style>
- <style name="SelectPrinterActivityTheme" parent="@android:style/Theme.Holo.Light">
+ <style name="SelectPrinterActivityTheme" parent="@android:style/Theme.DeviceDefault.Light">
<item name="android:actionBarStyle">@style/SelectPrinterActivityActionBarStyle</item>
</style>
- <style name="SelectPrinterActivityActionBarStyle" parent="@android:style/Widget.Holo.ActionBar">
+ <style name="SelectPrinterActivityActionBarStyle" parent="@android:style/Widget.DeviceDefault.Light.ActionBar">
<item name="android:displayOptions">showTitle</item>
</style>
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 29e8d1d..19286c8 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -1,3 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.shell"
coreApp="true"
@@ -83,7 +101,7 @@
<activity
android:name=".BugreportWarningActivity"
- android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true"
android:exported="false" />
diff --git a/packages/Shell/res/values-sk/strings.xml b/packages/Shell/res/values-sk/strings.xml
index 99f36f9..59c3ccf 100644
--- a/packages/Shell/res/values-sk/strings.xml
+++ b/packages/Shell/res/values-sk/strings.xml
@@ -17,8 +17,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Prostredie"</string>
- <string name="bugreport_finished_title" msgid="2293711546892863898">"Správa o chybách sa zaznamenala"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Dotykom môžete zdieľať správu o chybách"</string>
+ <string name="bugreport_finished_title" msgid="2293711546892863898">"Hlásenie o chybách bolo vytvorené"</string>
+ <string name="bugreport_finished_text" msgid="3559904746859400732">"Hlásenie o chybách môžete zdielať klepnutím"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Správy o chybách obsahujú údaje z rôznych súborov denníkov systému vrátane osobných a súkromných informácií. Zdieľajte ich iba s dôveryhodnými aplikáciami a ľuďmi."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Zobraziť túto správu nabudúce"</string>
</resources>
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index b09cc1d..3424eed 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -1,3 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.android.systemui"
@@ -157,7 +175,7 @@
<activity android:name=".usb.UsbConfirmActivity"
android:exported="true"
android:permission="android.permission.MANAGE_USB"
- android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true">
</activity>
@@ -166,7 +184,7 @@
<activity android:name=".usb.UsbPermissionActivity"
android:exported="true"
android:permission="android.permission.MANAGE_USB"
- android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true">
</activity>
@@ -175,7 +193,7 @@
<activity android:name=".usb.UsbResolverActivity"
android:exported="true"
android:permission="android.permission.MANAGE_USB"
- android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true">
</activity>
@@ -184,7 +202,7 @@
<activity android:name=".usb.UsbAccessoryUriActivity"
android:exported="true"
android:permission="android.permission.MANAGE_USB"
- android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true">
</activity>
@@ -192,7 +210,7 @@
<!-- started from UsbDebuggingManager -->
<activity android:name=".usb.UsbDebuggingActivity"
android:permission="android.permission.MANAGE_USB"
- android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true">
</activity>
@@ -202,7 +220,7 @@
android:name=".net.NetworkOverLimitActivity"
android:exported="true"
android:permission="android.permission.MANAGE_NETWORK_POLICY"
- android:theme="@android:style/Theme.Holo.Panel"
+ android:theme="@android:style/Theme.DeviceDefault.Light.Panel"
android:finishOnCloseSystemDialogs="true"
android:launchMode="singleTop"
android:taskAffinity="com.android.systemui.net"
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index f6e875c..f5ce222 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -26,7 +26,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top|center_horizontal"
- android:background="#88000000">
+ android:background="#e6444444">
<ImageView
android:id="@+id/activity_icon"
android:layout_width="@dimen/recents_task_view_icon_size"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 1693e01..a7ec064 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -24,19 +24,10 @@
android:id="@+id/notification_panel"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:background="@drawable/notification_panel_bg"
android:paddingTop="@dimen/notification_panel_padding_top"
android:layout_marginStart="@dimen/notification_panel_margin_left"
>
- <View
- android:id="@+id/handle"
- android:layout_width="match_parent"
- android:layout_height="@dimen/close_handle_height"
- android:background="@drawable/status_bar_close"
- android:visibility="invisible"
- />
-
<include
layout="@layout/carrier_label"
android:layout_height="@dimen/carrier_label_height"
@@ -69,6 +60,7 @@
/>
<FrameLayout
+ android:id="@+id/notification_container_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
@@ -77,21 +69,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
-
- <ScrollView
- android:id="@+id/scroll"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:fadingEdge="none"
- android:overScrollMode="ifContentScrolls"
- >
- <com.android.systemui.statusbar.policy.NotificationRowLayout
- android:id="@+id/latestItems"
+
+ <com.android.systemui.statusbar.stack.NotificationStackScrollLayout
+ android:id="@+id/notification_stack_scroller"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- systemui:rowHeight="@dimen/notification_row_min_height"
/>
- </ScrollView>
</FrameLayout>
</LinearLayout>
</com.android.systemui.statusbar.phone.NotificationPanelView><!-- end of sliding panel -->
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index d7457f0..2e116d0 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -20,7 +20,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="7164937344850004466">"የስርዓት UI"</string>
- <string name="status_bar_clear_all_button" msgid="7774721344716731603">"አጥራ"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"አጽዳ"</string>
<string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"ከዝርዝር አስወግድ"</string>
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"የትግበራ መረጃ"</string>
<string name="status_bar_no_recent_apps" msgid="6576392951053994640">"ምንም የቅርብ ጊዜ ትግበራዎች የሉም"</string>
@@ -136,7 +136,7 @@
<string name="accessibility_battery_level" msgid="7451474187113371965">"የባትሪ <xliff:g id="NUMBER">%d</xliff:g> መቶኛ።"</string>
<string name="accessibility_settings_button" msgid="799583911231893380">"የስርዓት ቅንብሮች"</string>
<string name="accessibility_notifications_button" msgid="4498000369779421892">"ማሳወቂያዎች"</string>
- <string name="accessibility_remove_notification" msgid="3603099514902182350">"ማሳወቂያ አጥራ"</string>
+ <string name="accessibility_remove_notification" msgid="3603099514902182350">"ማሳወቂያ አጽዳ"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ነቅቷል።"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS በማግኘት ላይ።"</string>
<string name="accessibility_tty_enabled" msgid="4613200365379426561">"TeleTypewriter ነቅቷል።"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 9c920f2..86c1eb96 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -183,8 +183,8 @@
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Lysstyrke"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Automatisk rotation"</string>
<string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotation er låst"</string>
- <string name="quick_settings_rotation_locked_portrait_label" msgid="1553131290066230775">"Låst i portræt"</string>
- <string name="quick_settings_rotation_locked_landscape_label" msgid="7216265671276086593">"Låst i landskab"</string>
+ <string name="quick_settings_rotation_locked_portrait_label" msgid="1553131290066230775">"Altid stående"</string>
+ <string name="quick_settings_rotation_locked_landscape_label" msgid="7216265671276086593">"Altid liggende"</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"Inputmetode"</string>
<string name="quick_settings_location_label" msgid="5011327048748762257">"Placering"</string>
<string name="quick_settings_location_off_label" msgid="7464544086507331459">"Placering fra"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 4999f71..f2a9850 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -198,7 +198,7 @@
<string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"No conectado"</string>
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No hay red."</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi desactivado"</string>
- <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Pantalla de Cast"</string>
+ <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Enviar contenido a pantalla"</string>
<string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brillo"</string>
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="quick_settings_inversion_label" msgid="1666358784283020762">"Modo de inversión de color"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 7671ef1..289d6c6 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -188,8 +188,8 @@
<string name="quick_settings_rotation_locked_portrait_label" msgid="1553131290066230775">"Bloccato in verticale"</string>
<string name="quick_settings_rotation_locked_landscape_label" msgid="7216265671276086593">"Bloccato in orizzontale"</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"Metodo di immissione"</string>
- <string name="quick_settings_location_label" msgid="5011327048748762257">"Geolocalizzazione"</string>
- <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Posizione non attiva"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"Geolocalizz."</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Geolocalizz. non attiva"</string>
<string name="quick_settings_media_device_label" msgid="1302906836372603762">"Dispositivo multimediale"</string>
<string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Solo chiamate di emergenza"</string>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index ab71371..76e7784 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -40,4 +40,7 @@
<!-- The fixed height of each tile -->
<dimen name="quick_settings_cell_height">100dp</dimen>
+
+ <!-- Width of the zen mode interstitial dialog. -->
+ <dimen name="zen_mode_dialog_width">384dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index c49b6c2..9d57586 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -183,7 +183,7 @@
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Svetlost"</string>
<string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Samodejno vrtenje"</string>
<string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Zaklenjeno vrtenje"</string>
- <string name="quick_settings_rotation_locked_portrait_label" msgid="1553131290066230775">"Zaklenjeno na navpično postavitev"</string>
+ <string name="quick_settings_rotation_locked_portrait_label" msgid="1553131290066230775">"Zaklenjeno na pokončno postavitev"</string>
<string name="quick_settings_rotation_locked_landscape_label" msgid="7216265671276086593">"Zaklenjeno na ležečo postavitev"</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"Način vnosa"</string>
<string name="quick_settings_location_label" msgid="5011327048748762257">"Lokacija"</string>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index ad4dcf9..45f6af3 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -51,4 +51,7 @@
<!-- How far to slide the panel out when you touch it -->
<!-- On tablets this is just the close_handle_height -->
<dimen name="peek_height">@dimen/close_handle_height</dimen>
+
+ <!-- Width of the zen mode interstitial dialog. -->
+ <dimen name="zen_mode_dialog_width">384dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index e53c1fb..7fb5868 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -116,7 +116,7 @@
<string name="accessibility_two_bars" msgid="6437363648385206679">"信号强度为两格。"</string>
<string name="accessibility_three_bars" msgid="2648241415119396648">"信号强度为三格。"</string>
<string name="accessibility_signal_full" msgid="9122922886519676839">"信号满格。"</string>
- <string name="accessibility_desc_on" msgid="2385254693624345265">"打开。"</string>
+ <string name="accessibility_desc_on" msgid="2385254693624345265">"开启。"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"关闭。"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"已连接。"</string>
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
@@ -189,7 +189,7 @@
<string name="quick_settings_rotation_locked_landscape_label" msgid="7216265671276086593">"锁定为横向"</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"输入法"</string>
<string name="quick_settings_location_label" msgid="5011327048748762257">"位置信息"</string>
- <string name="quick_settings_location_off_label" msgid="7464544086507331459">"位置信息服务已关闭"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"位置信息:关闭"</string>
<string name="quick_settings_media_device_label" msgid="1302906836372603762">"媒体设备"</string>
<string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"只能拨打紧急呼救电话"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index a59dc75..5cf0453 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -39,8 +39,6 @@
<color name="status_bar_clock_color">#FFFFFFFF</color>
<drawable name="notification_item_background_color">#ff111111</drawable>
<drawable name="notification_item_background_color_pressed">#ff454545</drawable>
- <color name="notification_icon_legacy_bg_color">#ff4285F4</color>
- <color name="notification_action_legacy_color_filter">#ff555555</color>
<!-- Tint color for inactive Quick Settings icons. -->
<color name="ic_qs_off">#ff404040</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1dd9300..77ab17b 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -56,10 +56,10 @@
<!-- Amount of time to hold off before showing the search panel when the user presses home -->
<integer name="config_show_search_delay">200</integer>
- <!-- Vibration duration for MultiWaveView used in SearchPanelView -->
+ <!-- Vibration duration for GlowPadView used in SearchPanelView -->
<integer translatable="false" name="config_vibration_duration">0</integer>
- <!-- Vibration duration for MultiWaveView used in SearchPanelView -->
+ <!-- Vibration duration for GlowPadView used in SearchPanelView -->
<integer translatable="false" name="config_search_panel_view_vibration_duration">20</integer>
<!-- The length of the vibration when the notification pops open. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index f4bfd10..38e1083 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -232,4 +232,22 @@
<!-- The size of the icon in the recents task view. -->
<dimen name="recents_task_view_icon_size">60dp</dimen>
+
+ <!-- Space below the notification stack -->
+ <dimen name="notification_stack_margin_bottom">0dp</dimen>
+
+ <!-- Space reserved for the cards behind the top card in the top stack -->
+ <dimen name="top_stack_peek_amount">24dp</dimen>
+
+ <!-- Space reserved for the cards behind the top card in the bottom stack -->
+ <dimen name="bottom_stack_peek_amount">18dp</dimen>
+
+ <!-- The side padding of the notifications-->
+ <dimen name="notification_side_padding">8dp</dimen>
+
+ <!-- Z distance between notifications if they are in the stack -->
+ <dimen name="z_distance_between_notifications">2dp</dimen>
+
+ <!-- Width of the zen mode interstitial dialog. -->
+ <dimen name="zen_mode_dialog_width">320dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 14af020..76cadd7 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -16,12 +16,12 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <style name="RecentsStyle" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
+ <style name="RecentsStyle" parent="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar">
<item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
</style>
<!-- Alternate Recents theme -->
- <style name="RecentsTheme" parent="@android:style/Theme.Holo.Wallpaper.NoTitleBar">
+ <style name="RecentsTheme" parent="@android:style/Theme.DeviceDefault.Wallpaper.NoTitleBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 48a6522..1832d37 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -34,6 +34,8 @@
import android.view.ViewConfiguration;
import android.view.ViewGroup;
+import com.android.systemui.statusbar.policy.ScrollAdapter;
+
public class ExpandHelper implements Gefingerpoken, OnClickListener {
public interface Callback {
View getChildAtRawPosition(float x, float y);
@@ -108,7 +110,7 @@
private int mGravity;
- private View mScrollView;
+ private ScrollAdapter mScrollAdapter;
private OnScaleGestureListener mScaleGestureListener
= new ScaleGestureDetector.SimpleOnScaleGestureListener() {
@@ -301,8 +303,8 @@
mGravity = gravity;
}
- public void setScrollView(View scrollView) {
- mScrollView = scrollView;
+ public void setScrollAdapter(ScrollAdapter adapter) {
+ mScrollAdapter = adapter;
}
private float calculateGlow(float target, float actual) {
@@ -384,7 +386,7 @@
}
return true;
}
- if (mScrollView != null && mScrollView.getScrollY() > 0) {
+ if (mScrollAdapter != null && !mScrollAdapter.isScrolledToTop()) {
return false;
}
// Now look for other gestures
@@ -407,7 +409,8 @@
}
case MotionEvent.ACTION_DOWN:
- mWatchingForPull = isInside(mScrollView, x, y);
+ mWatchingForPull = mScrollAdapter != null &&
+ isInside(mScrollAdapter.getHostView(), x, y);
mLastMotionY = y;
break;
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index 9d2d6ee..ab2ad96 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -368,7 +368,7 @@
final ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
final List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasksForUser(1,
- ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_RELATED,
+ ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_PROFILES,
UserHandle.CURRENT.getIdentifier());
TaskDescription item = null;
if (recentTasks.size() > 0) {
@@ -441,7 +441,7 @@
final List<ActivityManager.RecentTaskInfo> recentTasks =
am.getRecentTasks(MAX_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE
- | ActivityManager.RECENT_INCLUDE_RELATED);
+ | ActivityManager.RECENT_INCLUDE_PROFILES);
int numTasks = recentTasks.size();
ActivityInfo homeInfo = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME).resolveActivityInfo(pm, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
index f75ea92..7ab40b0 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsActivity.java
@@ -165,7 +165,7 @@
am.getRecentTasks(2,
ActivityManager.RECENT_WITH_EXCLUDED |
ActivityManager.RECENT_IGNORE_UNAVAILABLE |
- ActivityManager.RECENT_INCLUDE_RELATED);
+ ActivityManager.RECENT_INCLUDE_PROFILES);
if (recentTasks.size() > 1 &&
mRecentsPanel.simulateClick(recentTasks.get(1).persistentId)) {
// recents panel will take care of calling show(false) through simulateClick
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 1a616a0..8543b97 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -23,35 +23,26 @@
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
-import android.graphics.Paint;
import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.DisplayMetrics;
-import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.View;
import android.view.WindowManager;
import com.android.systemui.R;
-import com.android.systemui.RecentsComponent;
-import com.android.systemui.SystemUI;
import java.util.List;
@@ -113,6 +104,7 @@
final static String sRecentsService = "com.android.systemui.recents.RecentsService";
Context mContext;
+ SystemServicesProxy mSystemServicesProxy;
// Recents service binding
Messenger mService = null;
@@ -127,6 +119,7 @@
public AlternateRecentsComponent(Context context) {
mContext = context;
+ mSystemServicesProxy = new SystemServicesProxy(context);
mMessenger = new Messenger(new RecentsMessageHandler());
}
@@ -219,17 +212,16 @@
/** Loads the first task thumbnail */
Bitmap loadFirstTaskThumbnail() {
- ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(1,
- ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_RELATED,
+ SystemServicesProxy ssp = mSystemServicesProxy;
+ List<ActivityManager.RecentTaskInfo> tasks = ssp.getRecentTasks(1,
UserHandle.CURRENT.getIdentifier());
for (ActivityManager.RecentTaskInfo t : tasks) {
// Skip tasks in the home stack
- if (am.isInHomeStack(t.persistentId)) {
+ if (ssp.isInHomeStack(t.persistentId)) {
return null;
}
- Bitmap thumbnail = am.getTaskTopThumbnail(t.persistentId);
+ Bitmap thumbnail = ssp.getTaskThumbnail(t.persistentId);
return thumbnail;
}
return null;
@@ -237,13 +229,12 @@
/** Returns whether there is a first task */
boolean hasFirstTask() {
- ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(1,
- ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_RELATED,
+ SystemServicesProxy ssp = mSystemServicesProxy;
+ List<ActivityManager.RecentTaskInfo> tasks = ssp.getRecentTasks(1,
UserHandle.CURRENT.getIdentifier());
for (ActivityManager.RecentTaskInfo t : tasks) {
// Skip tasks in the home stack
- if (am.isInHomeStack(t.persistentId)) {
+ if (ssp.isInHomeStack(t.persistentId)) {
continue;
}
@@ -294,8 +285,8 @@
// If Recents is the front most activity, then we should just communicate with it directly
// to launch the first task or dismiss itself
- ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
+ SystemServicesProxy ssp = mSystemServicesProxy;
+ List<ActivityManager.RunningTaskInfo> tasks = ssp.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index b5950e9..8c5c8fa 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -26,11 +26,17 @@
public static final boolean Verbose = false;
public static class App {
- public static final boolean EnableTaskFiltering = false;
+ public static final boolean EnableTaskFiltering = true;
public static final boolean EnableTaskStackClipping = false;
public static final boolean EnableToggleNewRecentsActivity = false;
// This disables the bitmap and icon caches to
public static final boolean DisableBackgroundCache = false;
+ // For debugging, this enables us to create mock recents tasks
+ public static final boolean EnableSystemServicesProxy = false;
+ // For debugging, this defines the number of mock recents packages to create
+ public static final int SystemServicesProxyMockPackageCount = 12;
+ // For debugging, this defines the number of mock recents tasks to create
+ public static final int SystemServicesProxyMockTaskCount = 75;
// Timing certain paths
public static final String TimeRecentsStartupKey = "startup";
@@ -73,14 +79,16 @@
public static class RecentsTaskLoader {
// XXX: This should be calculated on the first load
public static final int PreloadFirstTasksCount = 5;
- // For debugging, this allows us to multiply the number of cards for each task
- public static final int TaskEntryMultiplier = 1;
}
public static class TaskStackView {
public static class Animation {
public static final int TaskRemovedReshuffleDuration = 200;
public static final int SnapScrollBackDuration = 650;
+ public static final int FilteredCurrentViewsDuration = 150;
+ public static final int FilteredNewViewsDuration = 200;
+ public static final int UnfilteredCurrentViewsDuration = 150;
+ public static final int UnfilteredNewViewsDuration = 200;
}
public static final int TaskStackOverscrollRange = 150;
@@ -107,7 +115,7 @@
public static final boolean AnimateFrontTaskIconOnEnterRecents = true;
public static final boolean AnimateFrontTaskIconOnLeavingRecents = true;
- public static final boolean UseRoundedCorners = true;
+ public static final boolean UseRoundedCorners = false;
public static final float RoundedCornerRadiusDps = 3;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index b65b864..2436aee 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.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
+import android.os.SystemService;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
@@ -54,8 +55,11 @@
finish();
}
} else if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
- // Dismiss recents and launch the first task if possible
- dismissRecentsIfVisible();
+ // Try and unfilter and filtered stacks
+ if (!mRecentsView.unfilterFilteredStacks()) {
+ // If there are no filtered stacks, dismiss recents and launch the first task
+ dismissRecentsIfVisible();
+ }
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 515cec1..22363bb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -66,7 +66,7 @@
// in a bottom inset
tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top, 0);
tsv.boundScroll();
- TaskViewTransform transform = tsv.getStackTransform(0);
+ TaskViewTransform transform = tsv.getStackTransform(0, tsv.getStackScroll());
Rect taskRect = new Rect(transform.rect);
data.putParcelable("taskRect", taskRect);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index b497b69..e375f08 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -20,7 +20,6 @@
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -109,6 +108,7 @@
Handler mLoadThreadHandler;
Handler mMainThreadHandler;
+ SystemServicesProxy mSystemServicesProxy;
TaskResourceLoadQueue mLoadQueue;
DrawableLruCache mIconCache;
BitmapLruCache mThumbnailCache;
@@ -135,6 +135,7 @@
Console.log(Constants.DebugFlags.App.TaskDataLoader, "[TaskResourceLoader|start]");
mContext = context;
mCancelled = false;
+ mSystemServicesProxy = new SystemServicesProxy(context);
// Notify the load thread to start loading
synchronized(mLoadThread) {
mLoadThread.notifyAll();
@@ -146,6 +147,7 @@
Console.log(Constants.DebugFlags.App.TaskDataLoader, "[TaskResourceLoader|stop]");
// Mark as cancelled for the thread to pick up
mCancelled = true;
+ mSystemServicesProxy = null;
// If we are waiting for the load queue for more tasks, then we can just reset the
// Context now, since nothing is using it
if (mWaitingOnLoadQueue) {
@@ -175,66 +177,60 @@
}
}
} else {
+ SystemServicesProxy ssp = mSystemServicesProxy;
+
// Load the next item from the queue
Pair<Task, Boolean> nextTaskData = mLoadQueue.nextTask();
final Task t = nextTaskData.first;
final boolean forceLoadTask = nextTaskData.second;
if (t != null) {
- try {
- Drawable loadIcon = mIconCache.get(t.key);
- Bitmap loadThumbnail = mThumbnailCache.get(t.key);
- Console.log(Constants.DebugFlags.App.TaskDataLoader,
- " [TaskResourceLoader|load]",
- t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail +
- " forceLoad: " + forceLoadTask);
- // Load the icon
- if (loadIcon == null || forceLoadTask) {
- PackageManager pm = mContext.getPackageManager();
- ActivityInfo info = pm.getActivityInfo(t.key.intent.getComponent(),
- PackageManager.GET_META_DATA);
- Drawable icon = info.loadIcon(pm);
- if (!mCancelled) {
- if (icon != null) {
- Console.log(Constants.DebugFlags.App.TaskDataLoader,
- " [TaskResourceLoader|loadIcon]",
- icon);
- loadIcon = icon;
- mIconCache.put(t.key, icon);
- }
- }
- }
- // Load the thumbnail
- if (loadThumbnail == null || forceLoadTask) {
- ActivityManager am = (ActivityManager)
- mContext.getSystemService(Context.ACTIVITY_SERVICE);
- Bitmap thumbnail = am.getTaskTopThumbnail(t.key.id);
- if (!mCancelled) {
- if (thumbnail != null) {
- Console.log(Constants.DebugFlags.App.TaskDataLoader,
- " [TaskResourceLoader|loadThumbnail]",
- thumbnail);
- loadThumbnail = thumbnail;
- mThumbnailCache.put(t.key, thumbnail);
- } else {
- Console.logError(mContext,
- "Failed to load task top thumbnail for: " +
- t.key.intent.getComponent().getPackageName());
- }
- }
- }
+ Drawable loadIcon = mIconCache.get(t.key);
+ Bitmap loadThumbnail = mThumbnailCache.get(t.key);
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
+ " [TaskResourceLoader|load]",
+ t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail +
+ " forceLoad: " + forceLoadTask);
+ // Load the icon
+ if (loadIcon == null || forceLoadTask) {
+ ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent());
+ Drawable icon = ssp.getActivityIcon(info);
if (!mCancelled) {
- // Notify that the task data has changed
- final Drawable newIcon = loadIcon;
- final Bitmap newThumbnail = loadThumbnail;
- mMainThreadHandler.post(new Runnable() {
- @Override
- public void run() {
- t.notifyTaskDataLoaded(newThumbnail, newIcon, forceLoadTask);
- }
- });
+ if (icon != null) {
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
+ " [TaskResourceLoader|loadIcon]",
+ icon);
+ loadIcon = icon;
+ mIconCache.put(t.key, icon);
+ }
}
- } catch (PackageManager.NameNotFoundException ne) {
- ne.printStackTrace();
+ }
+ // Load the thumbnail
+ if (loadThumbnail == null || forceLoadTask) {
+ Bitmap thumbnail = ssp.getTaskThumbnail(t.key.id);
+ if (!mCancelled) {
+ if (thumbnail != null) {
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
+ " [TaskResourceLoader|loadThumbnail]",
+ thumbnail);
+ loadThumbnail = thumbnail;
+ mThumbnailCache.put(t.key, thumbnail);
+ } else {
+ Console.logError(mContext,
+ "Failed to load task top thumbnail for: " +
+ t.key.baseIntent.getComponent().getPackageName());
+ }
+ }
+ }
+ if (!mCancelled) {
+ // Notify that the task data has changed
+ final Drawable newIcon = loadIcon;
+ final Bitmap newThumbnail = loadThumbnail;
+ mMainThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ t.notifyTaskDataLoaded(newThumbnail, newIcon, forceLoadTask);
+ }
+ });
}
}
@@ -296,6 +292,7 @@
public class RecentsTaskLoader {
static RecentsTaskLoader sInstance;
+ SystemServicesProxy mSystemServicesProxy;
DrawableLruCache mIconCache;
BitmapLruCache mThumbnailCache;
TaskResourceLoadQueue mLoadQueue;
@@ -324,7 +321,8 @@
"[RecentsTaskLoader|init]", "thumbnailCache: " + thumbnailCacheSize +
" iconCache: " + iconCacheSize);
- // Initialize the cache and loaders
+ // Initialize the proxy, cache and loaders
+ mSystemServicesProxy = new SystemServicesProxy(context);
mLoadQueue = new TaskResourceLoadQueue();
mIconCache = new DrawableLruCache(iconCacheSize);
mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
@@ -358,6 +356,11 @@
return sInstance;
}
+ /** Returns the system services proxy */
+ public SystemServicesProxy getSystemServicesProxy() {
+ return mSystemServicesProxy;
+ }
+
/** Reload the set of recent tasks */
SpaceNode reload(Context context, int preloadCount) {
Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
@@ -367,141 +370,129 @@
SpaceNode root = new SpaceNode(context);
root.setStack(stack);
- try {
- long t1 = System.currentTimeMillis();
+ long t1 = System.currentTimeMillis();
- PackageManager pm = context.getPackageManager();
- ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ // Get the recent tasks
+ SystemServicesProxy ssp = mSystemServicesProxy;
+ List<ActivityManager.RecentTaskInfo> tasks =
+ ssp.getRecentTasks(25, UserHandle.CURRENT.getIdentifier());
+ Collections.reverse(tasks);
+ Console.log(Constants.DebugFlags.App.TimeSystemCalls,
+ "[RecentsTaskLoader|getRecentTasks]",
+ "" + (System.currentTimeMillis() - t1) + "ms");
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
+ "[RecentsTaskLoader|tasks]", "" + tasks.size());
- // Get the recent tasks
- List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(25,
- ActivityManager.RECENT_IGNORE_UNAVAILABLE |
- ActivityManager.RECENT_INCLUDE_RELATED, UserHandle.CURRENT.getIdentifier());
- Collections.reverse(tasks);
- Console.log(Constants.DebugFlags.App.TimeSystemCalls,
- "[RecentsTaskLoader|getRecentTasks]",
- "" + (System.currentTimeMillis() - t1) + "ms");
- Console.log(Constants.DebugFlags.App.TaskDataLoader,
- "[RecentsTaskLoader|tasks]", "" + tasks.size());
+ // Remove home/recents tasks
+ Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
+ while (iter.hasNext()) {
+ ActivityManager.RecentTaskInfo t = iter.next();
- // Remove home/recents tasks
- Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
- while (iter.hasNext()) {
- ActivityManager.RecentTaskInfo t = iter.next();
-
- // Skip tasks in the home stack
- if (am.isInHomeStack(t.persistentId)) {
- iter.remove();
- continue;
- }
- // Skip tasks from this Recents package
- if (t.baseIntent.getComponent().getPackageName().equals(context.getPackageName())) {
- iter.remove();
- continue;
- }
+ // Skip tasks in the home stack
+ if (ssp.isInHomeStack(t.persistentId)) {
+ iter.remove();
+ continue;
}
+ // Skip tasks from this Recents package
+ if (t.baseIntent.getComponent().getPackageName().equals(context.getPackageName())) {
+ iter.remove();
+ continue;
+ }
+ }
- // Add each task to the task stack
- t1 = System.currentTimeMillis();
- int taskCount = tasks.size();
- for (int i = 0; i < taskCount; i++) {
- ActivityManager.RecentTaskInfo t = tasks.get(i);
- ActivityInfo info = pm.getActivityInfo(t.baseIntent.getComponent(),
- PackageManager.GET_META_DATA);
- String title = info.loadLabel(pm).toString();
- boolean isForemostTask = (i == (taskCount - 1));
+ // Add each task to the task stack
+ t1 = System.currentTimeMillis();
+ int taskCount = tasks.size();
+ for (int i = 0; i < taskCount; i++) {
+ ActivityManager.RecentTaskInfo t = tasks.get(i);
+ ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent());
+ String title = ssp.getActivityLabel(info);
+ boolean isForemostTask = (i == (taskCount - 1));
- // Preload the specified number of apps
- if (i >= (taskCount - preloadCount)) {
- Console.log(Constants.DebugFlags.App.TaskDataLoader,
- "[RecentsTaskLoader|preloadTask]",
- "i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
+ // Preload the specified number of apps
+ if (i >= (taskCount - preloadCount)) {
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
+ "[RecentsTaskLoader|preloadTask]",
+ "i: " + i + " task: " + t.baseIntent.getComponent().getPackageName());
- String label = (t.activityLabel == null ? title : t.activityLabel.toString());
- BitmapDrawable bd = null;
- if (t.activityIcon != null) {
- bd = new BitmapDrawable(res, t.activityIcon);
- }
- Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, label, bd);
+ String label = (t.activityLabel == null ? title : t.activityLabel.toString());
+ BitmapDrawable bd = null;
+ if (t.activityIcon != null) {
+ bd = new BitmapDrawable(res, t.activityIcon);
+ }
+ Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, label, bd);
- // Load the icon (if possible and not the foremost task, from the cache)
- if (task.icon != null) {
- mIconCache.put(task.key, task.icon);
- } else {
- if (!isForemostTask) {
- task.icon = mIconCache.get(task.key);
- if (task.icon != null) {
- // Even though we get things from the cache, we should update them
- // if they've changed in the bg
- tasksToForceLoad.add(task);
- }
- }
- if (task.icon == null) {
- task.icon = info.loadIcon(pm);
- if (task.icon != null) {
- mIconCache.put(task.key, task.icon);
- } else {
- task.icon = mDefaultIcon;
- }
- }
- }
-
- // Load the thumbnail (if possible and not the foremost task, from the cache)
+ // Load the icon (if possible and not the foremost task, from the cache)
+ if (task.icon != null) {
+ mIconCache.put(task.key, task.icon);
+ } else {
if (!isForemostTask) {
- task.thumbnail = mThumbnailCache.get(task.key);
- if (task.thumbnail != null) {
- // Even though we get things from the cache, we should update them if
- // they've changed in the bg
+ task.icon = mIconCache.get(task.key);
+ if (task.icon != null) {
+ // Even though we get things from the cache, we should update them
+ // if they've changed in the bg
tasksToForceLoad.add(task);
}
}
- if (task.thumbnail == null) {
- Console.log(Constants.DebugFlags.App.TaskDataLoader,
- "[RecentsTaskLoader|loadingTaskThumbnail]");
- task.thumbnail = am.getTaskTopThumbnail(t.id);
- if (task.thumbnail != null) {
- mThumbnailCache.put(task.key, task.thumbnail);
+ if (task.icon == null) {
+ task.icon = ssp.getActivityIcon(info);
+ if (task.icon != null) {
+ mIconCache.put(task.key, task.icon);
} else {
- task.thumbnail = mDefaultThumbnail;
+ task.icon = mDefaultIcon;
}
}
+ }
- // Create as many tasks a we want to multiply by
- for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
- Console.log(Constants.DebugFlags.App.TaskDataLoader,
- " [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
- stack.addTask(task);
- }
- } else {
- // Create as many tasks a we want to multiply by
- for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) {
- Console.log(Constants.DebugFlags.App.TaskDataLoader,
- " [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
- stack.addTask(new Task(t.persistentId, (t.id > -1), t.baseIntent, title,
- null, null));
+ // Load the thumbnail (if possible and not the foremost task, from the cache)
+ if (!isForemostTask) {
+ task.thumbnail = mThumbnailCache.get(task.key);
+ if (task.thumbnail != null) {
+ // Even though we get things from the cache, we should update them if
+ // they've changed in the bg
+ tasksToForceLoad.add(task);
}
}
- }
- Console.log(Constants.DebugFlags.App.TimeSystemCalls,
- "[RecentsTaskLoader|getAllTaskTopThumbnail]",
- "" + (System.currentTimeMillis() - t1) + "ms");
-
- /*
- // Get all the stacks
- t1 = System.currentTimeMillis();
- List<ActivityManager.StackInfo> stackInfos = ams.getAllStackInfos();
- Console.log(Constants.DebugFlags.App.TimeSystemCalls, "[RecentsTaskLoader|getAllStackInfos]", "" + (System.currentTimeMillis() - t1) + "ms");
- Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|stacks]", "" + tasks.size());
- for (ActivityManager.StackInfo s : stackInfos) {
- Console.log(Constants.DebugFlags.App.TaskDataLoader, " [RecentsTaskLoader|stack]", s.toString());
- if (stacks.containsKey(s.stackId)) {
- stacks.get(s.stackId).setRect(s.bounds);
+ if (task.thumbnail == null) {
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
+ "[RecentsTaskLoader|loadingTaskThumbnail]");
+ task.thumbnail = ssp.getTaskThumbnail(task.key.id);
+ if (task.thumbnail != null) {
+ mThumbnailCache.put(task.key, task.thumbnail);
+ } else {
+ task.thumbnail = mDefaultThumbnail;
+ }
}
+
+ // Add the task to the stack
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
+ " [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
+ stack.addTask(task);
+ } else {
+ // Add the task to the stack
+ Console.log(Constants.DebugFlags.App.TaskDataLoader,
+ " [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName());
+ stack.addTask(new Task(t.persistentId, (t.id > -1), t.baseIntent, title,
+ null, null));
}
- */
- } catch (Exception e) {
- e.printStackTrace();
}
+ Console.log(Constants.DebugFlags.App.TimeSystemCalls,
+ "[RecentsTaskLoader|getAllTaskTopThumbnail]",
+ "" + (System.currentTimeMillis() - t1) + "ms");
+
+ /*
+ // Get all the stacks
+ t1 = System.currentTimeMillis();
+ List<ActivityManager.StackInfo> stackInfos = ams.getAllStackInfos();
+ Console.log(Constants.DebugFlags.App.TimeSystemCalls, "[RecentsTaskLoader|getAllStackInfos]", "" + (System.currentTimeMillis() - t1) + "ms");
+ Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|stacks]", "" + tasks.size());
+ for (ActivityManager.StackInfo s : stackInfos) {
+ Console.log(Constants.DebugFlags.App.TaskDataLoader, " [RecentsTaskLoader|stack]", s.toString());
+ if (stacks.containsKey(s.stackId)) {
+ stacks.get(s.stackId).setRect(s.bounds);
+ }
+ }
+ */
// Start the task loader
mLoader.start(context);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
new file mode 100644
index 0000000..57d6524
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -0,0 +1,182 @@
+/*
+ * 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.app.ActivityOptions;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Acts as a shim around the real system services that we need to access data from, and provides
+ * a point of injection when testing UI.
+ */
+public class SystemServicesProxy {
+ ActivityManager mAm;
+ PackageManager mPm;
+ String mPackage;
+
+ Bitmap mDummyIcon;
+
+ /** Private constructor */
+ public SystemServicesProxy(Context context) {
+ mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ mPm = context.getPackageManager();
+ mPackage = context.getPackageName();
+
+ if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+ // Create a dummy icon
+ mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
+ Canvas c = new Canvas(mDummyIcon);
+ c.drawColor(0xFFFF0000);
+ c.setBitmap(null);
+ }
+ }
+
+ /** Returns a list of the recents tasks */
+ public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numTasks, int userId) {
+ if (mAm == null) return null;
+
+ // If we are mocking, then create some recent tasks
+ if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+ ArrayList<ActivityManager.RecentTaskInfo> tasks =
+ new ArrayList<ActivityManager.RecentTaskInfo>();
+ int count = Math.min(numTasks, Constants.DebugFlags.App.SystemServicesProxyMockTaskCount);
+ for (int i = 0; i < count; i++) {
+ // Create a dummy component name
+ int packageIndex = i % Constants.DebugFlags.App.SystemServicesProxyMockPackageCount;
+ ComponentName cn = new ComponentName("com.android.test" + packageIndex,
+ "com.android.test" + i + ".Activity");
+ // Create the recent task info
+ ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
+ rti.id = rti.persistentId = i;
+ rti.baseIntent = new Intent();
+ rti.baseIntent.setComponent(cn);
+ rti.description = rti.activityLabel = "Recent Task";
+ rti.activityIcon = Bitmap.createBitmap(mDummyIcon);
+ tasks.add(rti);
+ }
+ return tasks;
+ }
+
+ return mAm.getRecentTasksForUser(numTasks,
+ ActivityManager.RECENT_IGNORE_UNAVAILABLE |
+ ActivityManager.RECENT_INCLUDE_PROFILES, userId);
+ }
+
+ /** Returns a list of the running tasks */
+ public List<ActivityManager.RunningTaskInfo> getRunningTasks(int numTasks) {
+ if (mAm == null) return null;
+ return mAm.getRunningTasks(numTasks);
+ }
+
+ /** Returns whether the specified task is in the home stack */
+ public boolean isInHomeStack(int taskId) {
+ if (mAm == null) return false;
+
+ // If we are mocking, then just return false
+ if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+ return false;
+ }
+
+ return mAm.isInHomeStack(taskId);
+ }
+
+ /** Returns the top task thumbnail for the given task id */
+ public Bitmap getTaskThumbnail(int taskId) {
+ if (mAm == null) return null;
+
+ // If we are mocking, then just return a dummy thumbnail
+ if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+ Bitmap thumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(thumbnail);
+ c.drawColor(0xFF00ff00);
+ c.setBitmap(null);
+ return thumbnail;
+ }
+
+ return mAm.getTaskTopThumbnail(taskId);
+ }
+
+ /** Moves a task to the front with the specified activity options */
+ public void moveTaskToFront(int taskId, ActivityOptions opts) {
+ if (mAm == null) return;
+ if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
+
+ if (opts != null) {
+ mAm.moveTaskToFront(taskId, ActivityManager.MOVE_TASK_WITH_HOME,
+ opts.toBundle());
+ } else {
+ mAm.moveTaskToFront(taskId, ActivityManager.MOVE_TASK_WITH_HOME);
+ }
+ }
+
+ /** Removes the task and kills the process */
+ public void removeTask(int taskId) {
+ if (mAm == null) return;
+ if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
+
+ mAm.removeTask(taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
+ }
+
+ /** Returns the activity info for a given component name */
+ public ActivityInfo getActivityInfo(ComponentName cn) {
+ if (mPm == null) return null;
+ if (Constants.DebugFlags.App.EnableSystemServicesProxy) return null;
+
+ try {
+ return mPm.getActivityInfo(cn, PackageManager.GET_META_DATA);
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /** Returns the activity label */
+ public String getActivityLabel(ActivityInfo info) {
+ if (mPm == null) return null;
+
+ // If we are mocking, then return a mock label
+ if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+ return "Recent Task";
+ }
+
+ return info.loadLabel(mPm).toString();
+ }
+
+ /** Returns the activity icon */
+ public Drawable getActivityIcon(ActivityInfo info) {
+ if (mPm == null) return null;
+
+ // If we are mocking, then return a mock label
+ if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
+ return new ColorDrawable(0xFFff0000);
+ }
+
+ return info.loadIcon(mPm);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
index 33e4246..9048cba 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
@@ -20,9 +20,6 @@
/* Common code */
public class Utilities {
- public static final Rect tmpRect = new Rect();
- public static final Rect tmpRect2 = new Rect();
-
/** Scales a rect about its centroid */
public static void scaleRectAboutCenter(Rect r, float scale) {
if (scale != 1.0f) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index cda4ab2..25a9aeb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -19,7 +19,6 @@
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
-import com.android.systemui.recents.Constants;
/**
@@ -37,11 +36,11 @@
/* The Task Key represents the unique primary key for the task */
public static class TaskKey {
public final int id;
- public final Intent intent;
+ public final Intent baseIntent;
public TaskKey(int id, Intent intent) {
this.id = id;
- this.intent = intent;
+ this.baseIntent = intent;
}
@Override
@@ -56,7 +55,7 @@
@Override
public String toString() {
- return "Task.Key: " + id + ", " + intent.getComponent().getPackageName();
+ return "Task.Key: " + id + ", " + baseIntent.getComponent().getPackageName();
}
}
@@ -106,20 +105,13 @@
@Override
public boolean equals(Object o) {
- // If we have multiple task entries for the same task, then we do the simple object
- // equality check
- if (Constants.Values.RecentsTaskLoader.TaskEntryMultiplier > 1) {
- return super.equals(o);
- }
-
- // Otherwise, check that the id and intent match (the other fields can be asynchronously
- // loaded and is unsuitable to testing the identity of this Task)
+ // Check that the id matches
Task t = (Task) o;
return key.equals(t.key);
}
@Override
public String toString() {
- return "Task: " + key.intent.getComponent().getPackageName() + " [" + super.toString() + "]";
+ return "Task: " + key.baseIntent.getComponent().getPackageName() + " [" + super.toString() + "]";
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index f2f89ae..a0e5b6a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -39,9 +39,11 @@
TaskFilter mFilter;
/** Sets the task filter, saving the current touch state */
- void setFilter(TaskFilter filter) {
+ boolean setFilter(TaskFilter filter) {
+ ArrayList<Task> prevFilteredTasks = new ArrayList<Task>(mFilteredTasks);
mFilter = filter;
updateFilteredTasks();
+ return !prevFilteredTasks.equals(mFilteredTasks);
}
/** Removes the task filter and returns the previous touch state */
@@ -126,9 +128,9 @@
/* Notifies when a task has been removed from the stack */
public void onStackTaskRemoved(TaskStack stack, Task t);
/** Notifies when the stack was filtered */
- public void onStackFiltered(TaskStack stack);
+ public void onStackFiltered(TaskStack newStack, ArrayList<Task> curStack, Task t);
/** Notifies when the stack was un-filtered */
- public void onStackUnfiltered(TaskStack stack);
+ public void onStackUnfiltered(TaskStack newStack, ArrayList<Task> curStack);
}
Context mContext;
@@ -201,29 +203,30 @@
}
/** Filters the stack into tasks similar to the one specified */
- public void filterTasks(Task t) {
+ public void filterTasks(final Task t) {
+ ArrayList<Task> oldStack = new ArrayList<Task>(mTaskList.getTasks());
+
// Set the task list filter
- // XXX: This is a dummy filter that currently just accepts every other task.
- mTaskList.setFilter(new TaskFilter() {
+ boolean filtered = mTaskList.setFilter(new TaskFilter() {
@Override
- public boolean acceptTask(Task t, int i) {
- if (i % 2 == 0) {
- return true;
- }
- return false;
+ public boolean acceptTask(Task at, int i) {
+ return t.key.baseIntent.getComponent().getPackageName().equals(
+ at.key.baseIntent.getComponent().getPackageName());
}
});
- if (mCb != null) {
- mCb.onStackFiltered(this);
+ if (filtered && mCb != null) {
+ mCb.onStackFiltered(this, oldStack, t);
}
}
/** Unfilters the current stack */
public void unfilterTasks() {
+ ArrayList<Task> oldStack = new ArrayList<Task>(mTaskList.getTasks());
+
// Unset the filter, then update the virtual scroll
mTaskList.removeFilter();
if (mCb != null) {
- mCb.onStackUnfiltered(this);
+ mCb.onStackUnfiltered(this, oldStack);
}
}
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 cc85439..cb52794 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -16,7 +16,6 @@
package com.android.systemui.recents.views;
-import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.content.ActivityNotFoundException;
import android.content.Context;
@@ -30,6 +29,7 @@
import com.android.systemui.recents.Console;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
+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;
@@ -211,17 +211,18 @@
View sourceView = tv;
int offsetX = 0;
int offsetY = 0;
+ int stackScroll = stackView.getStackScroll();
if (tv == null) {
// If there is no actual task view, then use the stack view as the source view
// and then offset to the expected transform rect, but bound this to just
// outside the display rect (to ensure we don't animate from too far away)
RecentsConfiguration config = RecentsConfiguration.getInstance();
sourceView = stackView;
- transform = stackView.getStackTransform(stack.indexOfTask(task));
+ transform = stackView.getStackTransform(stack.indexOfTask(task), stackScroll);
offsetX = transform.rect.left;
offsetY = Math.min(transform.rect.top, config.displayRect.height());
} else {
- transform = stackView.getStackTransform(stack.indexOfTask(task));
+ transform = stackView.getStackTransform(stack.indexOfTask(task), stackScroll);
}
// Compute the thumbnail to scale up from
@@ -245,17 +246,11 @@
if (task.isActive) {
// Bring an active task to the foreground
- ActivityManager am = (ActivityManager)
- stackView.getContext().getSystemService(Context.ACTIVITY_SERVICE);
- if (opts != null) {
- am.moveTaskToFront(task.key.id, ActivityManager.MOVE_TASK_WITH_HOME,
- opts.toBundle());
- } else {
- am.moveTaskToFront(task.key.id, ActivityManager.MOVE_TASK_WITH_HOME);
- }
+ RecentsTaskLoader.getInstance().getSystemServicesProxy()
+ .moveTaskToFront(task.key.id, opts);
} else {
// Launch the activity with the desired animation
- Intent i = new Intent(task.key.intent);
+ Intent i = new Intent(task.key.baseIntent);
i.setFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
| Intent.FLAG_ACTIVITY_TASK_ON_HOME
| Intent.FLAG_ACTIVITY_NEW_TASK);
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 e7f517f..dfd608c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -18,10 +18,10 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
-import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
@@ -34,14 +34,15 @@
import android.view.ViewParent;
import android.widget.FrameLayout;
import android.widget.OverScroller;
+import com.android.systemui.R;
import com.android.systemui.recents.Console;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsTaskLoader;
+import com.android.systemui.recents.SystemServicesProxy;
import com.android.systemui.recents.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.R;
import java.util.ArrayList;
@@ -71,6 +72,7 @@
int mStackScroll;
int mMinScroll;
int mMaxScroll;
+ int mStashedScroll;
OverScroller mScroller;
ObjectAnimator mScrollAnimator;
@@ -79,6 +81,9 @@
int mStackViewsAnimationDuration;
boolean mStackViewsDirty = true;
boolean mAwaitingFirstLayout = true;
+ int[] mTmpVisibleRange = new int[2];
+ Rect mTmpRect = new Rect();
+ Rect mTmpRect2 = new Rect();
LayoutInflater mInflater;
public TaskStackView(Context context, TaskStack stack) {
@@ -102,7 +107,7 @@
}
void requestSynchronizeStackViewsWithModel(int duration) {
Console.log(Constants.DebugFlags.TaskStack.SynchronizeViewsWithModel,
- "[TaskStackView|requestSynchronize]", "", Console.AnsiYellow);
+ "[TaskStackView|requestSynchronize]", "" + duration + "ms", Console.AnsiYellow);
if (!mStackViewsDirty) {
invalidate();
}
@@ -128,14 +133,17 @@
}
/** Update/get the transform */
- public TaskViewTransform getStackTransform(int indexInStack) {
+ public TaskViewTransform getStackTransform(int indexInStack, int stackScroll) {
TaskViewTransform transform = new TaskViewTransform();
- // Map the items to an continuous position relative to the current scroll
+ // Return early if we have an invalid index
+ if (indexInStack < 0) return transform;
+
+ // Map the items to an continuous position relative to the specified scroll
int numPeekCards = Constants.Values.TaskStackView.StackPeekNumCards;
float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
float peekHeight = Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height();
- float t = ((indexInStack * overlapHeight) - getStackScroll()) / overlapHeight;
+ float t = ((indexInStack * overlapHeight) - stackScroll) / overlapHeight;
float boundedT = Math.max(t, -(numPeekCards + 1));
// Set the scale relative to its position
@@ -167,25 +175,57 @@
return transform;
}
+ /**
+ * Gets the stack transforms of a list of tasks, and returns the visible range of tasks.
+ */
+ private ArrayList<TaskViewTransform> getStackTransforms(ArrayList<Task> tasks,
+ int stackScroll,
+ int[] visibleRangeOut) {
+ // XXX: Optimization: Use binary search to find the visible range
+
+ ArrayList<TaskViewTransform> taskTransforms = new ArrayList<TaskViewTransform>();
+ int taskCount = tasks.size();
+ int firstVisibleIndex = -1;
+ int lastVisibleIndex = -1;
+ for (int i = 0; i < taskCount; i++) {
+ TaskViewTransform transform = getStackTransform(i, stackScroll);
+ taskTransforms.add(transform);
+ if (transform.visible) {
+ if (firstVisibleIndex < 0) {
+ firstVisibleIndex = i;
+ }
+ lastVisibleIndex = i;
+ }
+ }
+ if (visibleRangeOut != null) {
+ visibleRangeOut[0] = firstVisibleIndex;
+ visibleRangeOut[1] = lastVisibleIndex;
+ }
+ return taskTransforms;
+ }
+
/** Synchronizes the views with the model */
void synchronizeStackViewsWithModel() {
Console.log(Constants.DebugFlags.TaskStack.SynchronizeViewsWithModel,
"[TaskStackView|synchronizeViewsWithModel]",
"mStackViewsDirty: " + mStackViewsDirty, Console.AnsiYellow);
if (mStackViewsDirty) {
-
- // XXX: Optimization: Use binary search to find the visible range
- // XXX: Optimize to not call getStackTransform() so many times
// XXX: Consider using TaskViewTransform pool to prevent allocations
// XXX: Iterate children views, update transforms and remove all that are not visible
// For all remaining tasks, update transforms and if visible add the view
- // Update the visible state of all the tasks
+ // Get all the task transforms
+ int[] visibleRange = mTmpVisibleRange;
+ int stackScroll = getStackScroll();
ArrayList<Task> tasks = mStack.getTasks();
+ ArrayList<TaskViewTransform> taskTransforms = getStackTransforms(tasks, stackScroll,
+ visibleRange);
+
+ // Update the visible state of all the tasks
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
Task task = tasks.get(i);
- TaskViewTransform transform = getStackTransform(i);
+ TaskViewTransform transform = taskTransforms.get(i);
TaskView tv = getChildViewForTask(task);
if (transform.visible) {
@@ -194,11 +234,10 @@
// When we are picking up a new view from the view pool, prepare it for any
// following animation by putting it in a reasonable place
if (mStackViewsAnimationDuration > 0 && i != 0) {
- // XXX: We have to animate when filtering, etc. Maybe we should have a
- // runnable that ensures that tasks are animated in a special way
- // when they are entering the scene?
- int fromIndex = (transform.t < 0) ? (i - 1) : (i + 1);
- tv.updateViewPropertiesFromTask(null, getStackTransform(fromIndex), 0);
+ int fromIndex = (transform.t < 0) ? (visibleRange[0] - 1) :
+ (visibleRange[1] + 1);
+ tv.updateViewPropertiesToTaskTransform(null,
+ getStackTransform(fromIndex, stackScroll), 0);
}
}
} else {
@@ -208,17 +247,18 @@
}
}
- // Update all the current view children
+ // Update all the remaining view children
// NOTE: We have to iterate in reverse where because we are removing views directly
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
TaskView tv = (TaskView) getChildAt(i);
Task task = tv.getTask();
- TaskViewTransform transform = getStackTransform(mStack.indexOfTask(task));
- if (!transform.visible) {
+ int taskIndex = mStack.indexOfTask(task);
+ if (taskIndex < 0 || !taskTransforms.get(taskIndex).visible) {
mViewPool.returnViewToPool(tv);
} else {
- tv.updateViewPropertiesFromTask(null, transform, mStackViewsAnimationDuration);
+ tv.updateViewPropertiesToTaskTransform(null, taskTransforms.get(taskIndex),
+ mStackViewsAnimationDuration);
}
}
@@ -235,6 +275,10 @@
mStackScroll = value;
requestSynchronizeStackViewsWithModel();
}
+ /** Sets the current stack scroll without synchronizing the stack view with the model */
+ public void setStackScrollRaw(int value) {
+ mStackScroll = value;
+ }
/** Gets the current stack scroll */
public int getStackScroll() {
@@ -251,36 +295,39 @@
// Abort any current animations
abortScroller();
- if (mScrollAnimator != null) {
- mScrollAnimator.cancel();
- mScrollAnimator.removeAllListeners();
- }
+ abortBoundScrollAnimation();
// Start a new scroll animation
- mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
- mScrollAnimator.setDuration(duration);
- mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- setStackScroll((Integer) animation.getAnimatedValue());
- }
- });
- mScrollAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- // Disable hw layers on the stack
- decHwLayersRefCount("animateBoundScroll");
- }
- });
+ animateScroll(curScroll, newScroll, duration);
mScrollAnimator.start();
}
return mScrollAnimator;
}
+ /** Animates the stack scroll */
+ void animateScroll(int curScroll, int newScroll, int duration) {
+ mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
+ mScrollAnimator.setDuration(duration);
+ mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ setStackScroll((Integer) animation.getAnimatedValue());
+ }
+ });
+ mScrollAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ // Disable hw layers on the stack
+ decHwLayersRefCount("animateBoundScroll");
+ }
+ });
+ }
+
/** Aborts any current stack scrolls */
void abortBoundScrollAnimation() {
if (mScrollAnimator != null) {
mScrollAnimator.cancel();
+ mScrollAnimator.removeAllListeners();
}
}
@@ -304,6 +351,20 @@
return false;
}
+ /**
+ * Bounds the current scroll if necessary, but does not synchronize the stack view with the
+ * model.
+ */
+ public boolean boundScrollRaw() {
+ int curScroll = getStackScroll();
+ int newScroll = Math.max(mMinScroll, Math.min(mMaxScroll, curScroll));
+ if (newScroll != curScroll) {
+ setStackScrollRaw(newScroll);
+ return true;
+ }
+ return false;
+ }
+
/** Returns whether the current scroll is out of bounds */
boolean isScrollOutOfBounds() {
return (getStackScroll() < 0) || (getStackScroll() > mMaxScroll);
@@ -404,12 +465,12 @@
TaskView tv = (TaskView) child;
TaskView nextTv = null;
int curIndex = indexOfChild(tv);
- if (curIndex < (getChildCount() - 1)) {
+ if ((curIndex > -1) && (curIndex < (getChildCount() - 1))) {
// Clip against the next view (if we aren't animating its alpha)
nextTv = (TaskView) getChildAt(curIndex + 1);
if (nextTv.getAlpha() == 1f) {
- Rect curRect = tv.getClippingRect(Utilities.tmpRect, false);
- Rect nextRect = nextTv.getClippingRect(Utilities.tmpRect2, true);
+ Rect curRect = tv.getClippingRect(mTmpRect, false);
+ Rect nextRect = nextTv.getClippingRect(mTmpRect2, true);
RecentsConfiguration config = RecentsConfiguration.getInstance();
// The hit rects are relative to the task view, which needs to be offset by the
// system bar height
@@ -528,9 +589,7 @@
mTaskRect.right, mStackRectSansPeek.top + mTaskRect.height());
}
- if (!mAwaitingFirstLayout) {
- requestSynchronizeStackViewsWithModel();
- } else {
+ if (mAwaitingFirstLayout) {
mAwaitingFirstLayout = false;
}
}
@@ -570,13 +629,185 @@
}
@Override
- public void onStackFiltered(TaskStack stack) {
- requestSynchronizeStackViewsWithModel();
+ public void onStackFiltered(TaskStack newStack, final ArrayList<Task> curStack,
+ Task filteredTask) {
+ // NOTE: This code assumes that the current (unfiltered) stack is a superset of the new
+ // (filtered) stack
+ // XXX: Use HW Layers
+
+ // Stash the scroll for us to restore to when we unfilter
+ mStashedScroll = getStackScroll();
+
+ // Compute the transforms of the items in the current stack
+ final ArrayList<TaskViewTransform> curTaskTransforms =
+ getStackTransforms(curStack, mStashedScroll, null);
+
+ // Bound the new stack scroll
+ updateMinMaxScroll(false);
+ boundScrollRaw();
+
+ // Compute the transforms of the items in the new stack
+ final ArrayList<TaskViewTransform> taskTransforms =
+ getStackTransforms(mStack.getTasks(), getStackScroll(), null);
+
+ // Animate all of the existing views on screen either out of view (if they are not visible
+ // in the new stack) or to their final positions in the new stack
+ final ArrayList<TaskView> childrenToReturnToPool = new ArrayList<TaskView>();
+ final ArrayList<Task> tasks = mStack.getTasks();
+ ArrayList<Animator> childViewAnims = new ArrayList<Animator>();
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ TaskView tv = (TaskView) getChildAt(i);
+ Task task = tv.getTask();
+ TaskViewTransform toTransform;
+ int taskIndex = tasks.indexOf(task);
+ if ((taskIndex < 0) || !taskTransforms.get(taskIndex).visible) {
+ // Compose a new transform that animates the task view out of view
+ TaskViewTransform fromTransform = curTaskTransforms.get(curStack.indexOf(task));
+ toTransform = new TaskViewTransform(fromTransform);
+ tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
+ tv.prepareTaskTransformForFilterTaskHidden(toTransform);
+
+ childrenToReturnToPool.add(tv);
+ } else {
+ toTransform = taskTransforms.get(taskIndex);
+ }
+ childViewAnims.add(tv.getAnimatorToTaskTransform(toTransform));
+ }
+
+ AnimatorSet childViewAnimSet = new AnimatorSet();
+ childViewAnimSet.setDuration(
+ Constants.Values.TaskStackView.Animation.FilteredCurrentViewsDuration);
+ childViewAnimSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ // Return all the removed children to the view pool
+ for (TaskView tv : childrenToReturnToPool) {
+ mViewPool.returnViewToPool(tv);
+ }
+
+ // For views that are not already visible, animate them in
+ int taskCount = tasks.size();
+ for (int i = 0; i < taskCount; i++) {
+ Task task = tasks.get(i);
+ TaskViewTransform toTransform = taskTransforms.get(i);
+ if (toTransform.visible) {
+ TaskViewTransform fromTransform =
+ curTaskTransforms.get(curStack.indexOf(task));
+ TaskView tv = getChildViewForTask(task);
+ if (tv == null) {
+ tv = mViewPool.pickUpViewFromPool(task, task);
+
+ // Animate from the current position to the new position
+ tv.prepareTaskTransformForFilterTaskVisible(fromTransform);
+ tv.updateViewPropertiesToTaskTransform(fromTransform,
+ toTransform,
+ Constants.Values.TaskStackView.Animation.FilteredNewViewsDuration);
+ }
+ }
+ }
+ invalidate();
+ }
+ });
+ childViewAnimSet.playTogether(childViewAnims);
+ childViewAnimSet.start();
}
@Override
- public void onStackUnfiltered(TaskStack stack) {
- requestSynchronizeStackViewsWithModel();
+ public void onStackUnfiltered(TaskStack newStack, final ArrayList<Task> curStack) {
+ // Compute the transforms of the items in the current stack
+ final int curScroll = getStackScroll();
+ final ArrayList<TaskViewTransform> curTaskTransforms =
+ getStackTransforms(curStack, curScroll, null);
+
+ // Restore the stashed scroll
+ updateMinMaxScroll(false);
+ setStackScrollRaw(mStashedScroll);
+ boundScrollRaw();
+
+ // Compute the transforms of the items in the new stack
+ final ArrayList<TaskViewTransform> taskTransforms =
+ getStackTransforms(mStack.getTasks(), getStackScroll(), null);
+
+ // Animate all of the existing views out of view (if they are not in the visible range in
+ // the new stack) or to their final positions in the new stack
+ final ArrayList<TaskView> childrenToRemove = new ArrayList<TaskView>();
+ final ArrayList<Task> tasks = mStack.getTasks();
+ ArrayList<Animator> childViewAnims = new ArrayList<Animator>();
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ TaskView tv = (TaskView) getChildAt(i);
+ Task task = tv.getTask();
+ int taskIndex = tasks.indexOf(task);
+ TaskViewTransform transform;
+
+ // If the view is no longer visible, then we should just animate it out
+ if (taskIndex < 0 || !taskTransforms.get(taskIndex).visible) {
+ transform = new TaskViewTransform(curTaskTransforms.get(curStack.indexOf(task)));
+ tv.prepareTaskTransformForFilterTaskVisible(transform);
+ childrenToRemove.add(tv);
+ } else {
+ transform = taskTransforms.get(taskIndex);
+ }
+ childViewAnims.add(tv.getAnimatorToTaskTransform(transform));
+ }
+
+ AnimatorSet childViewAnimSet = new AnimatorSet();
+ childViewAnimSet.setDuration(
+ Constants.Values.TaskStackView.Animation.UnfilteredCurrentViewsDuration);
+ childViewAnimSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ // Return all the removed children to the view pool
+ for (TaskView tv : childrenToRemove) {
+ mViewPool.returnViewToPool(tv);
+ }
+
+ // Increment the hw layers ref count
+ addHwLayersRefCount("unfilteredNewViews");
+
+ // For views that are not already visible, animate them in
+ ArrayList<Animator> newViewAnims = new ArrayList<Animator>();
+ AnimatorSet newViewAnimSet = new AnimatorSet();
+ int taskCount = tasks.size();
+ int offset = 0;
+ for (int i = 0; i < taskCount; i++) {
+ Task task = tasks.get(i);
+ TaskViewTransform toTransform = taskTransforms.get(i);
+ if (toTransform.visible) {
+ TaskView tv = getChildViewForTask(task);
+ if (tv == null) {
+ // For views that are not already visible, animate them in
+ tv = mViewPool.pickUpViewFromPool(task, task);
+
+ // Animate in this new view
+ TaskViewTransform fromTransform = new TaskViewTransform(toTransform);
+ tv.prepareTaskTransformForFilterTaskHidden(fromTransform);
+ tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
+ newViewAnims.add(tv.getAnimatorToTaskTransform(toTransform));
+ offset++;
+ }
+ }
+ }
+
+ // Run the animation
+ newViewAnimSet.setDuration(
+ Constants.Values.TaskStackView.Animation.UnfilteredNewViewsDuration);
+ newViewAnimSet.playTogether(newViewAnims);
+ newViewAnimSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ // Decrement the hw layers ref count
+ decHwLayersRefCount("unfilteredNewViews");
+ }
+ });
+ newViewAnimSet.start();
+
+ invalidate();
+ }
+ });
+ childViewAnimSet.playTogether(childViewAnims);
+ childViewAnimSet.start();
}
/**** ViewPoolConsumer Implementation ****/
@@ -845,7 +1076,7 @@
/** Handles touch events once we have intercepted them */
public boolean onTouchEvent(MotionEvent ev) {
- Console.log(Constants.DebugFlags.TaskStack.SynchronizeViewsWithModel,
+ Console.log(Constants.DebugFlags.UI.TouchEvents,
"[TaskStackViewTouchHandler|touchEvent]",
Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
@@ -1038,16 +1269,19 @@
loader.deleteTaskData(task);
// Remove the task from activity manager
- final ActivityManager am = (ActivityManager)
- activity.getSystemService(Context.ACTIVITY_SERVICE);
- if (am != null) {
- am.removeTask(tv.getTask().key.id,
- ActivityManager.REMOVE_TASK_KILL_PROCESS);
- }
+ RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(tv.getTask().key.id);
- // If there are no remaining tasks, then just close the activity
+ // 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) {
- activity.finish();
+ boolean shouldFinishActivity = true;
+ if (mSv.mStack.hasFilteredTasks()) {
+ mSv.mStack.unfilterTasks();
+ shouldFinishActivity = (mSv.mStack.getTaskCount() == 0);
+ }
+ if (shouldFinishActivity) {
+ activity.finish();
+ }
}
// Disable HW layers
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 c86b0e1..e04a1b2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -16,6 +16,9 @@
package com.android.systemui.recents.views;
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
@@ -72,6 +75,7 @@
// Bind the views
mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
+ mBarView.mActivityIcon.setOnClickListener(this);
if (mTaskDataLoaded) {
onTaskDataLoaded(false);
}
@@ -90,12 +94,16 @@
}
@Override
- protected void onDraw(Canvas canvas) {
+ protected void dispatchDraw(Canvas canvas) {
+ int restoreCount = 0;
if (Constants.Values.TaskView.UseRoundedCorners) {
+ restoreCount = canvas.save();
canvas.clipPath(mRoundedRectClipPath);
}
-
- super.onDraw(canvas);
+ super.dispatchDraw(canvas);
+ if (Constants.Values.TaskView.UseRoundedCorners) {
+ canvas.restoreToCount(restoreCount);
+ }
}
/** Set callback */
@@ -109,27 +117,43 @@
}
/** Synchronizes this view's properties with the task's transform */
- void updateViewPropertiesFromTask(TaskViewTransform animateFromTransform,
- TaskViewTransform transform, int duration) {
+ void updateViewPropertiesToTaskTransform(TaskViewTransform animateFromTransform,
+ TaskViewTransform toTransform, int duration) {
if (duration > 0) {
if (animateFromTransform != null) {
setTranslationY(animateFromTransform.translationY);
setScaleX(animateFromTransform.scale);
setScaleY(animateFromTransform.scale);
+ setAlpha(animateFromTransform.alpha);
}
- animate().translationY(transform.translationY)
- .scaleX(transform.scale)
- .scaleY(transform.scale)
+ animate().translationY(toTransform.translationY)
+ .scaleX(toTransform.scale)
+ .scaleY(toTransform.scale)
+ .alpha(toTransform.alpha)
.setDuration(duration)
.setInterpolator(new AccelerateDecelerateInterpolator())
+ .withLayer()
.start();
} else {
- setTranslationY(transform.translationY);
- setScaleX(transform.scale);
- setScaleY(transform.scale);
+ setTranslationY(toTransform.translationY);
+ setScaleX(toTransform.scale);
+ setScaleY(toTransform.scale);
+ setAlpha(toTransform.alpha);
}
}
+ /** Returns an animator to animate this task to the specified transform */
+ Animator getAnimatorToTaskTransform(TaskViewTransform toTransform) {
+ AnimatorSet anims = new AnimatorSet();
+ anims.playTogether(
+ ObjectAnimator.ofFloat(this, "translationY", toTransform.translationY),
+ ObjectAnimator.ofFloat(this, "scaleX", toTransform.scale),
+ ObjectAnimator.ofFloat(this, "scaleY", toTransform.scale),
+ ObjectAnimator.ofFloat(this, "alpha", toTransform.alpha)
+ );
+ return anims;
+ }
+
/** Resets this view's properties */
void resetViewProperties() {
setTranslationX(0f);
@@ -139,6 +163,17 @@
setAlpha(1f);
}
+ void prepareTaskTransformForFilterTaskHidden(TaskViewTransform toTransform) {
+ // Fade the view out and slide it away
+ toTransform.alpha = 0f;
+ toTransform.translationY += 200;
+ }
+
+ void prepareTaskTransformForFilterTaskVisible(TaskViewTransform fromTransform) {
+ // Fade the view in
+ fromTransform.alpha = 0f;
+ }
+
/** Animates this task view as it enters recents */
public void animateOnEnterRecents() {
RecentsConfiguration config = RecentsConfiguration.getInstance();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
index 66c52a0..0748bbb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -23,13 +23,27 @@
public class TaskViewTransform {
public int translationY = 0;
public float scale = 1f;
- public boolean visible = true;
+ public float alpha = 1f;
+ public boolean visible = false;
public Rect rect = new Rect();
float t;
+ public TaskViewTransform() {
+ // Do nothing
+ }
+
+ public TaskViewTransform(TaskViewTransform o) {
+ translationY = o.translationY;
+ scale = o.scale;
+ alpha = o.alpha;
+ visible = o.visible;
+ rect.set(o.rect);
+ t = o.t;
+ }
+
@Override
public String toString() {
- return "TaskViewTransform y: " + translationY + " scale: " + scale +
+ return "TaskViewTransform y: " + translationY + " scale: " + scale + " alpha: " + alpha +
" visible: " + visible + " rect: " + rect;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index e516bb8..5771299 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -172,6 +172,7 @@
.setContentTitle(r.getString(R.string.screenshot_saving_title))
.setContentText(r.getString(R.string.screenshot_saving_text))
.setSmallIcon(R.drawable.stat_notify_image)
+ .setCategory(Notification.CATEGORY_PROGRESS)
.setWhen(now);
mNotificationBuilder.setPublicVersion(mPublicNotificationBuilder.build());
@@ -694,6 +695,7 @@
.setSmallIcon(R.drawable.stat_notify_image_error)
.setWhen(System.currentTimeMillis())
.setVisibility(Notification.VISIBILITY_PUBLIC) // ok to show outside lockscreen
+ .setCategory(Notification.CATEGORY_ERROR)
.setAutoCancel(true);
Notification n =
new Notification.BigTextStyle(b)
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
index d584043..c99f691 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
@@ -83,22 +83,7 @@
}
public void onCheckedChanged(CompoundButton toggle, boolean checked) {
- Drawable thumb;
- Drawable slider;
- final Resources res = getContext().getResources();
- if (checked) {
- thumb = res.getDrawable(
- com.android.internal.R.drawable.scrubber_control_disabled_holo);
- slider = res.getDrawable(
- R.drawable.status_bar_settings_slider_disabled);
- } else {
- thumb = res.getDrawable(
- com.android.internal.R.drawable.scrubber_control_selector_holo);
- slider = res.getDrawable(
- com.android.internal.R.drawable.scrubber_progress_horizontal_holo_dark);
- }
- mSlider.setThumb(thumb);
- mSlider.setProgressDrawable(slider);
+ mSlider.setEnabled(checked);
if (mListener != null) {
mListener.onChanged(this, mTracking, checked, mSlider.getProgress());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 68c8364..f349036 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -29,14 +29,9 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
-import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.database.ContentObserver;
-import android.graphics.Color;
-import android.graphics.PorterDuff;
import android.graphics.Rect;
-import android.graphics.drawable.AnimationDrawable;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
@@ -52,14 +47,10 @@
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.service.notification.StatusBarNotification;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
import android.text.TextUtils;
-import android.text.style.TextAppearanceSpan;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
-import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.IWindowManager;
import android.view.LayoutInflater;
@@ -70,7 +61,6 @@
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
-import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
@@ -80,18 +70,17 @@
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.widget.SizeAdaptiveLayout;
-import com.android.systemui.ImageUtils;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.SearchPanelView;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.phone.KeyguardTouchDelegate;
-import com.android.systemui.statusbar.policy.NotificationRowLayout;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import java.util.ArrayList;
import java.util.Locale;
-import java.util.Stack;
public abstract class BaseStatusBar extends SystemUI implements
CommandQueue.Callbacks {
@@ -129,7 +118,7 @@
// all notifications
protected NotificationData mNotificationData = new NotificationData();
- protected NotificationRowLayout mPile;
+ protected NotificationStackScrollLayout mStackScroller;
protected NotificationData.Entry mInterruptingNotificationEntry;
protected long mInterruptingNotificationTime;
@@ -143,7 +132,7 @@
protected PopupMenu mNotificationBlamePopup;
protected int mCurrentUserId = 0;
- final protected SparseArray<UserInfo> mRelatedUsers = new SparseArray<UserInfo>();
+ final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();
protected int mLayoutDirection = -1; // invalid
private Locale mLocale;
@@ -157,8 +146,7 @@
// public mode, private notifications, etc
private boolean mLockscreenPublicMode = false;
private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
- private Context mLightThemeContext;
- private ImageUtils mImageUtils = new ImageUtils();
+ private LegacyNotificationUtil mLegacyNotificationUtil = LegacyNotificationUtil.getInstance();
private UserManager mUserManager;
@@ -254,21 +242,21 @@
String action = intent.getAction();
if (Intent.ACTION_USER_SWITCHED.equals(action)) {
mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
- updateRelatedUserCache();
+ updateCurrentProfilesCache();
if (true) Log.v(TAG, "userId " + mCurrentUserId + " is in the house");
userSwitched(mCurrentUserId);
} else if (Intent.ACTION_USER_ADDED.equals(action)) {
- updateRelatedUserCache();
+ updateCurrentProfilesCache();
}
}
};
- private void updateRelatedUserCache() {
- synchronized (mRelatedUsers) {
- mRelatedUsers.clear();
+ private void updateCurrentProfilesCache() {
+ synchronized (mCurrentProfiles) {
+ mCurrentProfiles.clear();
if (mUserManager != null) {
- for (UserInfo related : mUserManager.getRelatedUsers(mCurrentUserId)) {
- mRelatedUsers.put(related.id, related);
+ for (UserInfo user : mUserManager.getProfiles(mCurrentUserId)) {
+ mCurrentProfiles.put(user.id, user);
}
}
}
@@ -296,8 +284,6 @@
true,
mLockscreenSettingsObserver,
UserHandle.USER_ALL);
- mLightThemeContext = new RemoteViewsThemeContextWrapper(mContext,
- android.R.style.Theme_Holo_Light);
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -373,24 +359,23 @@
filter.addAction(Intent.ACTION_USER_ADDED);
mContext.registerReceiver(mBroadcastReceiver, filter);
- updateRelatedUserCache();
+ updateCurrentProfilesCache();
}
public void userSwitched(int newUserId) {
// should be overridden
}
- public boolean notificationIsForCurrentOrRelatedUser(StatusBarNotification n) {
+ public boolean notificationIsForCurrentProfiles(StatusBarNotification n) {
final int thisUserId = mCurrentUserId;
final int notificationUserId = n.getUserId();
if (DEBUG && MULTIUSER_DEBUG) {
Log.v(TAG, String.format("%s: current userid: %d, notification userid: %d",
n, thisUserId, notificationUserId));
}
- synchronized (mRelatedUsers) {
+ synchronized (mCurrentProfiles) {
return notificationUserId == UserHandle.USER_ALL
- || thisUserId == notificationUserId
- || mRelatedUsers.get(notificationUserId) != null;
+ || mCurrentProfiles.get(notificationUserId) != null;
}
}
@@ -458,158 +443,6 @@
}
}
- private void processLegacyHoloNotification(StatusBarNotification sbn, View content) {
-
- // TODO: Also skip processing if it is a holo-style notification.
- // If the notification is custom, we can't process it.
- if (!sbn.getNotification().extras.getBoolean(Notification.EXTRA_BUILDER_REMOTE_VIEWS)) {
- return;
- }
-
- processLegacyHoloLargeIcon(content);
- processLegacyHoloActions(content);
- processLegacyNotificationIcon(content);
- processLegacyTextViews(content);
- }
-
- /**
- * @return the context to be used for the inflation of the specified {@code sbn}; this is
- * dependent whether the notification is quantum-style or holo-style
- */
- private Context getInflationContext(StatusBarNotification sbn) {
-
- // TODO: Adjust this logic when we change the theme of the status bar windows.
- if (sbn.getNotification().extras.getBoolean(Notification.EXTRA_BUILDER_REMOTE_VIEWS)) {
- return mLightThemeContext;
- } else {
- return mContext;
- }
- }
-
- private void processLegacyNotificationIcon(View content) {
- View v = content.findViewById(com.android.internal.R.id.right_icon);
- if (v != null & v instanceof ImageView) {
- ImageView iv = (ImageView) v;
- Drawable d = iv.getDrawable();
- if (isMonochrome(d)) {
- d.mutate();
- d.setColorFilter(mLightThemeContext.getResources().getColor(
- R.color.notification_action_legacy_color_filter), PorterDuff.Mode.MULTIPLY);
- }
- }
- }
-
- private void processLegacyHoloLargeIcon(View content) {
- View v = content.findViewById(com.android.internal.R.id.icon);
- if (v != null & v instanceof ImageView) {
- ImageView iv = (ImageView) v;
- if (isMonochrome(iv.getDrawable())) {
- iv.setBackground(mLightThemeContext.getResources().getDrawable(
- R.drawable.notification_icon_legacy_bg_inset));
- }
- }
- }
-
- private boolean isMonochrome(Drawable d) {
- if (d == null) {
- return false;
- } else if (d instanceof BitmapDrawable) {
- BitmapDrawable bd = (BitmapDrawable) d;
- return bd.getBitmap() != null && mImageUtils.isGrayscale(bd.getBitmap());
- } else if (d instanceof AnimationDrawable) {
- AnimationDrawable ad = (AnimationDrawable) d;
- int count = ad.getNumberOfFrames();
- return count > 0 && isMonochrome(ad.getFrame(0));
- } else {
- return false;
- }
- }
-
- private void processLegacyHoloActions(View content) {
- View v = content.findViewById(com.android.internal.R.id.actions);
- if (v != null & v instanceof ViewGroup) {
- ViewGroup vg = (ViewGroup) v;
- int childCount = vg.getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = vg.getChildAt(i);
- if (child instanceof Button) {
- Button button = (Button) child;
- Drawable[] compoundDrawables = button.getCompoundDrawablesRelative();
- if (isMonochrome(compoundDrawables[0])) {
- Drawable d = compoundDrawables[0];
- d.mutate();
- d.setColorFilter(mLightThemeContext.getResources().getColor(
- R.color.notification_action_legacy_color_filter),
- PorterDuff.Mode.MULTIPLY);
- }
- }
- }
- }
- }
-
- private void processLegacyTextViews(View content) {
- Stack<View> viewStack = new Stack<View>();
- viewStack.push(content);
- while(!viewStack.isEmpty()) {
- View current = viewStack.pop();
- if(current instanceof ViewGroup){
- ViewGroup currentGroup = (ViewGroup) current;
- int numChildren = currentGroup.getChildCount();
- for(int i=0;i<numChildren;i++){
- viewStack.push(currentGroup.getChildAt(i));
- }
- }
- if (current instanceof TextView) {
- processLegacyTextView((TextView) current);
- }
- }
- }
-
- private void processLegacyTextView(TextView textView) {
- if (textView.getText() instanceof Spanned) {
- Spanned ss = (Spanned) textView.getText();
- Object[] spans = ss.getSpans(0, ss.length(), Object.class);
- SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
- for (Object span : spans) {
- Object resultSpan = span;
- if (span instanceof TextAppearanceSpan) {
- resultSpan = processTextAppearanceSpan((TextAppearanceSpan) span);
- }
- builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span),
- ss.getSpanFlags(span));
- }
- textView.setText(builder);
- }
- }
-
- private TextAppearanceSpan processTextAppearanceSpan(TextAppearanceSpan span) {
- ColorStateList colorStateList = span.getTextColor();
- if (colorStateList != null) {
- int[] colors = colorStateList.getColors();
- boolean changed = false;
- for (int i = 0; i < colors.length; i++) {
- if (mImageUtils.isGrayscale(colors[i])) {
- colors[i] = processColor(colors[i]);
- changed = true;
- }
- }
- if (changed) {
- return new TextAppearanceSpan(
- span.getFamily(), span.getTextStyle(), span.getTextSize(),
- new ColorStateList(colorStateList.getStates(), colors),
- span.getLinkTextColor());
- }
- }
- return span;
- }
-
- private int processColor(int color) {
- return Color.argb(Color.alpha(color),
- 255 - Color.red(color),
- 255 - Color.green(color),
- 255 - Color.blue(color));
- }
-
private void startApplicationDetailsActivity(String packageName) {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.fromParts("package", packageName, null));
@@ -947,10 +780,10 @@
View contentViewLocal = null;
View bigContentViewLocal = null;
try {
- contentViewLocal = contentView.apply(getInflationContext(sbn), expanded,
+ contentViewLocal = contentView.apply(mContext, expanded,
mOnClickHandler);
if (bigContentView != null) {
- bigContentViewLocal = bigContentView.apply(getInflationContext(sbn), expanded,
+ bigContentViewLocal = bigContentView.apply(mContext, expanded,
mOnClickHandler);
}
}
@@ -983,8 +816,8 @@
View publicViewLocal = null;
if (publicNotification != null) {
try {
- publicViewLocal = publicNotification.contentView.apply(getInflationContext(sbn),
- expandedPublic, mOnClickHandler);
+ publicViewLocal = publicNotification.contentView.apply(mContext, expandedPublic,
+ mOnClickHandler);
if (publicViewLocal != null) {
publicViewLocal.setIsRootNamespace(true);
@@ -1005,7 +838,8 @@
if (publicViewLocal == null) {
// Add a basic notification template
publicViewLocal = LayoutInflater.from(mContext).inflate(
- com.android.internal.R.layout.notification_template_base, expandedPublic, true);
+ com.android.internal.R.layout.notification_template_quantum_base,
+ expandedPublic, true);
final TextView title = (TextView) publicViewLocal.findViewById(com.android.internal.R.id.title);
try {
@@ -1024,7 +858,12 @@
entry.notification.getNotification().number,
entry.notification.getNotification().tickerText);
- icon.setImageDrawable(StatusBarIconView.getIcon(mContext, ic));
+ Drawable iconDrawable = StatusBarIconView.getIcon(mContext, ic);
+ icon.setImageDrawable(iconDrawable);
+ if (mLegacyNotificationUtil.isGrayscale(iconDrawable)) {
+ icon.setBackgroundResource(
+ com.android.internal.R.drawable.notification_icon_legacy_bg_inset);
+ }
final TextView text = (TextView) publicViewLocal.findViewById(com.android.internal.R.id.text);
text.setText("Unlock your device to see this notification.");
@@ -1035,13 +874,6 @@
row.setDrawingCacheEnabled(true);
applyLegacyRowBackground(sbn, content);
- processLegacyHoloNotification(sbn, contentViewLocal);
- if (bigContentViewLocal != null) {
- processLegacyHoloNotification(sbn, bigContentViewLocal);
- }
- if (publicViewLocal != null) {
- processLegacyHoloNotification(sbn, publicViewLocal);
- }
if (MULTIUSER_DEBUG) {
TextView debug = (TextView) row.findViewById(R.id.debug_info);
@@ -1199,7 +1031,7 @@
}
// Construct the expanded view.
NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
- if (!inflateViews(entry, mPile)) {
+ if (!inflateViews(entry, mStackScroller)) {
handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
+ notification);
return null;
@@ -1260,8 +1092,7 @@
}
private boolean shouldIntercept() {
- return mZenMode == Settings.Global.ZEN_MODE_LIMITED
- || mZenMode == Settings.Global.ZEN_MODE_FULL;
+ return mZenMode != Settings.Global.ZEN_MODE_OFF;
}
protected boolean shouldIntercept(Notification n) {
@@ -1424,7 +1255,7 @@
updateNotificationVetoButton(oldEntry.row, notification);
// Is this for you?
- boolean isForCurrentUser = notificationIsForCurrentOrRelatedUser(notification);
+ boolean isForCurrentUser = notificationIsForCurrentProfiles(notification);
if (DEBUG) Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
// Restart the ticker if it's still running
@@ -1459,17 +1290,13 @@
: null;
// Reapply the RemoteViews
- contentView.reapply(getInflationContext(notification), entry.expanded, mOnClickHandler);
- processLegacyHoloNotification(notification, entry.expanded);
+ contentView.reapply(mContext, entry.expanded, mOnClickHandler);
if (bigContentView != null && entry.getBigContentView() != null) {
- bigContentView.reapply(getInflationContext(notification), entry.getBigContentView(),
+ bigContentView.reapply(mContext, entry.getBigContentView(),
mOnClickHandler);
- processLegacyHoloNotification(notification, entry.getBigContentView());
}
if (publicContentView != null && entry.getPublicContentView() != null) {
- publicContentView.reapply(getInflationContext(notification),
- entry.getPublicContentView(), mOnClickHandler);
- processLegacyHoloNotification(notification, entry.getPublicContentView());
+ publicContentView.reapply(mContext, entry.getPublicContentView(), mOnClickHandler);
}
// update the contentIntent
final PendingIntent contentIntent = notification.getNotification().contentIntent;
@@ -1540,35 +1367,4 @@
}
mContext.unregisterReceiver(mBroadcastReceiver);
}
-
- /**
- * A custom context theme wrapper that applies a platform theme to a created package context.
- * This is useful if you want to inflate {@link RemoteViews} with a custom theme (normally, the
- * theme used there is the default platform theme).
- */
- private static class RemoteViewsThemeContextWrapper extends ContextThemeWrapper {
-
- private int mThemeRes;
-
- private RemoteViewsThemeContextWrapper(Context base, int themeres) {
- super(base, themeres);
- mThemeRes = themeres;
- }
-
- @Override
- public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
- throws NameNotFoundException {
- Context c = super.createPackageContextAsUser(packageName, flags, user);
- c.setTheme(mThemeRes);
- return c;
- }
-
- @Override
- public Context createPackageContext(String packageName, int flags)
- throws NameNotFoundException {
- Context c = super.createPackageContext(packageName, flags);
- c.setTheme(mThemeRes);
- return c;
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 6be6d4d..2d2f2f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -17,45 +17,51 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.util.EventLog;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
-import com.android.systemui.EventLogTags;
import com.android.systemui.R;
import com.android.systemui.statusbar.GestureRecorder;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
public class NotificationPanelView extends PanelView {
public static final boolean DEBUG_GESTURES = true;
- Drawable mHandleBar;
- int mHandleBarHeight;
- View mHandleView;
- int mFingers;
PhoneStatusBar mStatusBar;
- boolean mOkToFlip;
+ private NotificationStackScrollLayout mNotificationStackScroller;
+ private int[] mTempLocation = new int[2];
+ private int[] mTempChildLocation = new int[2];
+ private View mNotificationParent;
+
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setStatusBar(PhoneStatusBar bar) {
+ if (mStatusBar != null) {
+ mStatusBar.setOnFlipRunnable(null);
+ }
mStatusBar = bar;
+ if (bar != null) {
+ mStatusBar.setOnFlipRunnable(new Runnable() {
+ @Override
+ public void run() {
+ requestPanelHeightUpdate();
+ }
+ });
+ }
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- Resources resources = getContext().getResources();
- mHandleBar = resources.getDrawable(R.drawable.status_bar_close);
- mHandleBarHeight = resources.getDimensionPixelSize(R.dimen.close_handle_height);
- mHandleView = findViewById(R.id.handle);
+ mNotificationStackScroller = (NotificationStackScrollLayout)
+ findViewById(R.id.notification_stack_scroller);
+ mNotificationParent = findViewById(R.id.notification_container_parent);
}
@Override
@@ -80,61 +86,86 @@
return super.dispatchPopulateAccessibilityEvent(event);
}
- // We draw the handle ourselves so that it's always glued to the bottom of the window.
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- if (changed) {
- final int pl = getPaddingLeft();
- final int pr = getPaddingRight();
- mHandleBar.setBounds(pl, 0, getWidth() - pr, (int) mHandleBarHeight);
- }
- }
-
- @Override
- public void draw(Canvas canvas) {
- super.draw(canvas);
- final int off = (int) (getHeight() - mHandleBarHeight - getPaddingBottom());
- canvas.translate(0, off);
- mHandleBar.setState(mHandleView.getDrawableState());
- mHandleBar.draw(canvas);
- canvas.translate(0, -off);
+ /**
+ * Gets the relative position of a view on the screen in regard to this view.
+ *
+ * @param requestedView the view we want to find the relative position for
+ * @return
+ */
+ private int getRelativeTop(View requestedView) {
+ getLocationOnScreen(mTempLocation);
+ requestedView.getLocationOnScreen(mTempChildLocation);
+ return mTempChildLocation[1] - mTempLocation[1];
}
@Override
public boolean onTouchEvent(MotionEvent event) {
- if (DEBUG_GESTURES) {
- if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
- EventLog.writeEvent(EventLogTags.SYSUI_NOTIFICATIONPANEL_TOUCH,
- event.getActionMasked(), (int) event.getX(), (int) event.getY());
- }
+ // TODO: Handle doublefinger swipe to notifications again. Look at history for a reference
+ // implementation.
+ return super.onTouchEvent(event);
+ }
+
+ @Override
+ protected boolean isScrolledToBottom() {
+ if (!isInSettings()) {
+ return mNotificationStackScroller.isScrolledToBottom();
}
- if (PhoneStatusBar.SETTINGS_DRAG_SHORTCUT && mStatusBar.mHasFlipSettings) {
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- mOkToFlip = getExpandedHeight() == 0;
- break;
- case MotionEvent.ACTION_POINTER_DOWN:
- if (mOkToFlip) {
- float miny = event.getY(0);
- float maxy = miny;
- for (int i=1; i<event.getPointerCount(); i++) {
- final float y = event.getY(i);
- if (y < miny) miny = y;
- if (y > maxy) maxy = y;
- }
- if (maxy - miny < mHandleBarHeight) {
- if (getMeasuredHeight() < mHandleBarHeight) {
- mStatusBar.switchToSettings();
- } else {
- mStatusBar.flipToSettings();
- }
- mOkToFlip = false;
- }
- }
- break;
- }
+ return super.isScrolledToBottom();
+ }
+
+ @Override
+ protected int getMaxPanelHeight() {
+ if (!isInSettings()) {
+ int maxPanelHeight = super.getMaxPanelHeight();
+ int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin();
+ return maxPanelHeight - emptyBottomMargin;
}
- return mHandleView.dispatchTouchEvent(event);
+ return super.getMaxPanelHeight();
+ }
+
+ private boolean isInSettings() {
+ return mStatusBar != null && mStatusBar.isFlippedToSettings();
+ }
+
+ @Override
+ protected void onHeightUpdated(float expandedHeight) {
+ updateNotificationStackHeight(expandedHeight);
+ }
+
+ /**
+ * Update the height of the {@link #mNotificationStackScroller} to the new expanded height.
+ * This is much more efficient than doing it over the layout pass.
+ *
+ * @param expandedHeight the new expanded height
+ */
+ private void updateNotificationStackHeight(float expandedHeight) {
+ float childOffset = getRelativeTop(mNotificationStackScroller)
+ - mNotificationParent.getTranslationY();
+ int newStackHeight = (int) (expandedHeight - childOffset);
+ int itemHeight = mNotificationStackScroller.getItemHeight();
+ int bottomStackPeekSize = mNotificationStackScroller.getBottomStackPeekSize();
+ int minStackHeight = itemHeight + bottomStackPeekSize;
+ if (newStackHeight >= minStackHeight) {
+ mNotificationParent.setTranslationY(0);
+ mNotificationStackScroller.setCurrentStackHeight(newStackHeight);
+ } else {
+
+ // We did not reach the position yet where we actually start growing,
+ // so we translate the stack upwards.
+ int translationY = (newStackHeight - minStackHeight);
+ // A slight parallax effect is introduced in order for the stack to catch up with
+ // the top card.
+ float partiallyThere = (float) newStackHeight / minStackHeight;
+ partiallyThere = Math.max(0, partiallyThere);
+ translationY += (1 - partiallyThere) * bottomStackPeekSize;
+ mNotificationParent.setTranslationY(translationY);
+ mNotificationStackScroller.setCurrentStackHeight(
+ (int) (expandedHeight - (childOffset + translationY)));
+ }
+ }
+
+ @Override
+ protected int getDesiredMeasureHeight() {
+ return mMaxPanelHeight;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 4b2c3e1..3c8af30 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -25,6 +25,7 @@
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewConfiguration;
import android.widget.FrameLayout;
import com.android.systemui.R;
@@ -69,7 +70,7 @@
private View mHandleView;
private float mPeekHeight;
- private float mTouchOffset;
+ private float mInitialOffsetOnTouch;
private float mExpandedFraction = 0;
private float mExpandedHeight = 0;
private boolean mJustPeeked;
@@ -77,6 +78,7 @@
private boolean mRubberbanding;
private boolean mTracking;
private int mTrackingPointer;
+ private int mTouchSlop;
private TimeAnimator mTimeAnimator;
private ObjectAnimator mPeekAnimator;
@@ -198,7 +200,6 @@
}
}
- private int[] mAbsPos = new int[2];
PanelBar mBar;
private final TimeListener mAnimationCallback = new TimeListener() {
@@ -220,7 +221,7 @@
};
private float mVel, mAccel;
- private int mFullHeight = 0;
+ protected int mMaxPanelHeight = 0;
private String mViewName;
protected float mInitialTouchY;
protected float mFinalTouchY;
@@ -253,13 +254,13 @@
mTimeAnimator.start();
mRubberbanding = mRubberbandingEnabled // is it enabled at all?
- && mExpandedHeight > getFullHeight() // are we past the end?
+ && mExpandedHeight > getMaxPanelHeight() // are we past the end?
&& mVel >= -mFlingGestureMinDistPx; // was this not possibly a "close" gesture?
if (mRubberbanding) {
mClosing = true;
} else if (mVel == 0) {
// if the panel is less than halfway open, close it
- mClosing = (mFinalTouchY / getFullHeight()) < 0.5f;
+ mClosing = (mFinalTouchY / getMaxPanelHeight()) < 0.5f;
} else {
mClosing = mExpandedHeight > 0 && mVel < 0;
}
@@ -268,7 +269,7 @@
if (DEBUG) logf("tick: v=%.2fpx/s dt=%.4fs", mVel, dt);
if (DEBUG) logf("tick: before: h=%d", (int) mExpandedHeight);
- final float fh = getFullHeight();
+ final float fh = getMaxPanelHeight();
boolean braking = false;
if (BRAKES) {
if (mClosing) {
@@ -351,6 +352,9 @@
mPeekHeight = res.getDimension(R.dimen.peek_height)
+ getPaddingBottom() // our window might have a dropshadow
- (mHandleView == null ? 0 : mHandleView.getPaddingTop()); // the handle might have a topshadow
+
+ final ViewConfiguration configuration = ViewConfiguration.get(getContext());
+ mTouchSlop = configuration.getScaledTouchSlop();
}
private void trackMovement(MotionEvent event) {
@@ -363,10 +367,221 @@
event.offsetLocation(-deltaX, -deltaY);
}
- // Pass all touches along to the handle, allowing the user to drag the panel closed from its interior
@Override
public boolean onTouchEvent(MotionEvent event) {
- return mHandleView.dispatchTouchEvent(event);
+
+ /*
+ * We capture touch events here and update the expand height here in case according to
+ * the users fingers. This also handles multi-touch.
+ *
+ * If the user just clicks shortly, we give him a quick peek of the shade.
+ *
+ * Flinging is also enabled in order to open or close the shade.
+ */
+
+ int pointerIndex = event.findPointerIndex(mTrackingPointer);
+ if (pointerIndex < 0) {
+ pointerIndex = 0;
+ mTrackingPointer = event.getPointerId(pointerIndex);
+ }
+ final float y = event.getY(pointerIndex);
+
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ mTracking = true;
+ if (mHandleView != null) {
+ mHandleView.setPressed(true);
+ postInvalidate(); // catch the press state change
+ }
+
+ mInitialTouchY = y;
+ initVelocityTracker();
+ trackMovement(event);
+ mTimeAnimator.cancel(); // end any outstanding animations
+ mBar.onTrackingStarted(PanelView.this);
+ mInitialOffsetOnTouch = mExpandedHeight;
+ if (mExpandedHeight == 0) {
+ mJustPeeked = true;
+ runPeekAnimation();
+ }
+ break;
+
+ case MotionEvent.ACTION_POINTER_UP:
+ final int upPointer = event.getPointerId(event.getActionIndex());
+ if (mTrackingPointer == upPointer) {
+ // gesture is ongoing, find a new pointer to track
+ final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
+ final float newY = event.getY(newIndex);
+ mTrackingPointer = event.getPointerId(newIndex);
+ mInitialOffsetOnTouch = mExpandedHeight;
+ mInitialTouchY = newY;
+ }
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ final float h = y - mInitialTouchY + mInitialOffsetOnTouch;
+ if (h > mPeekHeight) {
+ if (mPeekAnimator != null && mPeekAnimator.isStarted()) {
+ mPeekAnimator.cancel();
+ }
+ mJustPeeked = false;
+ }
+ if (!mJustPeeked) {
+ setExpandedHeightInternal(h);
+ mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
+ }
+
+ trackMovement(event);
+ break;
+
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ mFinalTouchY = y;
+ mTracking = false;
+ mTrackingPointer = -1;
+ if (mHandleView != null) {
+ mHandleView.setPressed(false);
+ postInvalidate(); // catch the press state change
+ }
+ mBar.onTrackingStopped(PanelView.this);
+ trackMovement(event);
+
+ float vel = getCurrentVelocity();
+ fling(vel, true);
+
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+ break;
+ }
+ return true;
+ }
+
+ private float getCurrentVelocity() {
+ float vel = 0;
+ float yVel = 0, xVel = 0;
+ boolean negative = false;
+
+ // the velocitytracker might be null if we got a bad input stream
+ if (mVelocityTracker == null) {
+ return 0;
+ }
+
+ mVelocityTracker.computeCurrentVelocity(1000);
+
+ yVel = mVelocityTracker.getYVelocity();
+ negative = yVel < 0;
+
+ xVel = mVelocityTracker.getXVelocity();
+ if (xVel < 0) {
+ xVel = -xVel;
+ }
+ if (xVel > mFlingGestureMaxXVelocityPx) {
+ xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
+ }
+
+ vel = (float) Math.hypot(yVel, xVel);
+ if (vel > mFlingGestureMaxOutputVelocityPx) {
+ vel = mFlingGestureMaxOutputVelocityPx;
+ }
+
+ // if you've barely moved your finger, we treat the velocity as 0
+ // preventing spurious flings due to touch screen jitter
+ final float deltaY = Math.abs(mFinalTouchY - mInitialTouchY);
+ if (deltaY < mFlingGestureMinDistPx
+ || vel < mFlingExpandMinVelocityPx
+ ) {
+ vel = 0;
+ }
+
+ if (negative) {
+ vel = -vel;
+ }
+
+ if (DEBUG) {
+ logf("gesture: dy=%f vel=(%f,%f) vlinear=%f",
+ deltaY,
+ xVel, yVel,
+ vel);
+ }
+ return vel;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent event) {
+
+ /*
+ * If the user drags anywhere inside the panel we intercept it if he moves his finger
+ * upwards. This allows closing the shade from anywhere inside the panel.
+ *
+ * We only do this if the current content is scrolled to the bottom,
+ * i.e isScrolledToBottom() is true and therefore there is no conflicting scrolling gesture
+ * possible.
+ */
+ int pointerIndex = event.findPointerIndex(mTrackingPointer);
+ if (pointerIndex < 0) {
+ pointerIndex = 0;
+ mTrackingPointer = event.getPointerId(pointerIndex);
+ }
+ final float y = event.getY(pointerIndex);
+ boolean scrolledToBottom = isScrolledToBottom();
+
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ mTracking = true;
+ if (mHandleView != null) {
+ mHandleView.setPressed(true);
+ // catch the press state change
+ postInvalidate();
+ }
+ mInitialTouchY = y;
+ initVelocityTracker();
+ trackMovement(event);
+ mTimeAnimator.cancel(); // end any outstanding animations
+ if (mExpandedHeight == 0 || y > getContentHeight()) {
+ return true;
+ }
+ break;
+ case MotionEvent.ACTION_POINTER_UP:
+ final int upPointer = event.getPointerId(event.getActionIndex());
+ if (mTrackingPointer == upPointer) {
+ // gesture is ongoing, find a new pointer to track
+ final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
+ mTrackingPointer = event.getPointerId(newIndex);
+ final float newY = event.getY(newIndex);
+ mInitialTouchY = newY;
+ }
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ final float h = y - mInitialTouchY;
+ trackMovement(event);
+ if (scrolledToBottom) {
+ if (h < -mTouchSlop) {
+ mInitialOffsetOnTouch = mExpandedHeight;
+ mInitialTouchY = y;
+ return true;
+ }
+ }
+ break;
+ }
+ return false;
+ }
+
+ private void initVelocityTracker() {
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ }
+ mVelocityTracker = FlingTracker.obtain();
+ }
+
+ protected boolean isScrolledToBottom() {
+ return false;
+ }
+
+ protected float getContentHeight() {
+ return mExpandedHeight;
}
@Override
@@ -375,134 +590,6 @@
mHandleView = findViewById(R.id.handle);
loadDimens();
-
- if (DEBUG) logf("handle view: " + mHandleView);
- if (mHandleView != null) {
- mHandleView.setOnTouchListener(new View.OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- int pointerIndex = event.findPointerIndex(mTrackingPointer);
- if (pointerIndex < 0) {
- pointerIndex = 0;
- mTrackingPointer = event.getPointerId(pointerIndex);
- }
- final float y = event.getY(pointerIndex);
- final float rawDelta = event.getRawY() - event.getY();
- final float rawY = y + rawDelta;
- if (DEBUG) logf("handle.onTouch: a=%s p=[%d,%d] y=%.1f rawY=%.1f off=%.1f",
- MotionEvent.actionToString(event.getAction()),
- mTrackingPointer, pointerIndex,
- y, rawY, mTouchOffset);
- PanelView.this.getLocationOnScreen(mAbsPos);
-
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- mTracking = true;
- mHandleView.setPressed(true);
- postInvalidate(); // catch the press state change
- mInitialTouchY = y;
- mVelocityTracker = FlingTracker.obtain();
- trackMovement(event);
- mTimeAnimator.cancel(); // end any outstanding animations
- mBar.onTrackingStarted(PanelView.this);
- mTouchOffset = (rawY - mAbsPos[1]) - mExpandedHeight;
- if (mExpandedHeight == 0) {
- mJustPeeked = true;
- runPeekAnimation();
- }
- break;
-
- case MotionEvent.ACTION_POINTER_UP:
- final int upPointer = event.getPointerId(event.getActionIndex());
- if (mTrackingPointer == upPointer) {
- // gesture is ongoing, find a new pointer to track
- final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
- final float newY = event.getY(newIndex);
- final float newRawY = newY + rawDelta;
- mTrackingPointer = event.getPointerId(newIndex);
- mTouchOffset = (newRawY - mAbsPos[1]) - mExpandedHeight;
- mInitialTouchY = newY;
- }
- break;
-
- case MotionEvent.ACTION_MOVE:
- final float h = rawY - mAbsPos[1] - mTouchOffset;
- if (h > mPeekHeight) {
- if (mPeekAnimator != null && mPeekAnimator.isStarted()) {
- mPeekAnimator.cancel();
- }
- mJustPeeked = false;
- }
- if (!mJustPeeked) {
- PanelView.this.setExpandedHeightInternal(h);
- mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
- }
-
- trackMovement(event);
- break;
-
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL:
- mFinalTouchY = y;
- mTracking = false;
- mTrackingPointer = -1;
- mHandleView.setPressed(false);
- postInvalidate(); // catch the press state change
- mBar.onTrackingStopped(PanelView.this);
- trackMovement(event);
-
- float vel = 0, yVel = 0, xVel = 0;
- boolean negative = false;
-
- if (mVelocityTracker != null) {
- // the velocitytracker might be null if we got a bad input stream
- mVelocityTracker.computeCurrentVelocity(1000);
-
- yVel = mVelocityTracker.getYVelocity();
- negative = yVel < 0;
-
- xVel = mVelocityTracker.getXVelocity();
- if (xVel < 0) {
- xVel = -xVel;
- }
- if (xVel > mFlingGestureMaxXVelocityPx) {
- xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
- }
-
- vel = (float)Math.hypot(yVel, xVel);
- if (vel > mFlingGestureMaxOutputVelocityPx) {
- vel = mFlingGestureMaxOutputVelocityPx;
- }
-
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
-
- // if you've barely moved your finger, we treat the velocity as 0
- // preventing spurious flings due to touch screen jitter
- final float deltaY = Math.abs(mFinalTouchY - mInitialTouchY);
- if (deltaY < mFlingGestureMinDistPx
- || vel < mFlingExpandMinVelocityPx
- ) {
- vel = 0;
- }
-
- if (negative) {
- vel = -vel;
- }
-
- if (DEBUG) logf("gesture: dy=%f vel=(%f,%f) vlinear=%f",
- deltaY,
- xVel, yVel,
- vel);
-
- fling(vel, true);
-
- break;
- }
- return true;
- }});
- }
}
public void fling(float vel, boolean always) {
@@ -543,19 +630,18 @@
// Did one of our children change size?
int newHeight = getMeasuredHeight();
- if (newHeight != mFullHeight) {
- mFullHeight = newHeight;
- // If the user isn't actively poking us, let's rubberband to the content
- if (!mTracking && !mRubberbanding && !mTimeAnimator.isStarted()
- && mExpandedHeight > 0 && mExpandedHeight != mFullHeight) {
- mExpandedHeight = mFullHeight;
- }
+ if (newHeight != mMaxPanelHeight) {
+ mMaxPanelHeight = newHeight;
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(
- (int) mExpandedHeight, MeasureSpec.AT_MOST); // MeasureSpec.getMode(heightMeasureSpec));
+ getDesiredMeasureHeight(), MeasureSpec.AT_MOST);
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
+ protected int getDesiredMeasureHeight() {
+ return (int) mExpandedHeight;
+ }
+
public void setExpandedHeight(float height) {
if (DEBUG) logf("setExpandedHeight(%.1f)", height);
@@ -569,8 +655,20 @@
@Override
protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
- if (DEBUG) logf("onLayout: changed=%s, bottom=%d eh=%d fh=%d", changed?"T":"f", bottom, (int)mExpandedHeight, mFullHeight);
+ if (DEBUG) logf("onLayout: changed=%s, bottom=%d eh=%d fh=%d", changed?"T":"f", bottom,
+ (int)mExpandedHeight, mMaxPanelHeight);
super.onLayout(changed, left, top, right, bottom);
+ requestPanelHeightUpdate();
+ }
+
+ protected void requestPanelHeightUpdate() {
+ float currentMaxPanelHeight = getMaxPanelHeight();
+
+ // If the user isn't actively poking us, let's update the height
+ if (!mTracking && !mRubberbanding && !mTimeAnimator.isStarted()
+ && mExpandedHeight > 0 && currentMaxPanelHeight != mExpandedHeight) {
+ setExpandedHeightInternal(currentMaxPanelHeight);
+ }
}
public void setExpandedHeightInternal(float h) {
@@ -583,7 +681,7 @@
h = 0;
}
- float fh = getFullHeight();
+ float fh = getMaxPanelHeight();
if (fh == 0) {
// Hmm, full height hasn't been computed yet
}
@@ -593,9 +691,13 @@
mExpandedHeight = h;
- if (DEBUG) logf("setExpansion: height=%.1f fh=%.1f tracking=%s rubber=%s", h, fh, mTracking?"T":"f", mRubberbanding?"T":"f");
+ if (DEBUG) {
+ logf("setExpansion: height=%.1f fh=%.1f tracking=%s rubber=%s", h, fh,
+ mTracking ? "T" : "f", mRubberbanding ? "T" : "f");
+ }
- requestLayout();
+ onHeightUpdated(mExpandedHeight);
+
// FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
// lp.height = (int) mExpandedHeight;
// setLayoutParams(lp);
@@ -603,13 +705,23 @@
mExpandedFraction = Math.min(1f, (fh == 0) ? 0 : h / fh);
}
- private float getFullHeight() {
- if (mFullHeight <= 0) {
- if (DEBUG) logf("Forcing measure() since fullHeight=" + mFullHeight);
+ protected void onHeightUpdated(float expandedHeight) {
+ requestLayout();
+ }
+
+ /**
+ * This returns the maximum height of the panel. Children should override this if their
+ * desired height is not the full height.
+ *
+ * @return the default implementation simply returns the maximum height.
+ */
+ protected int getMaxPanelHeight() {
+ if (mMaxPanelHeight <= 0) {
+ if (DEBUG) logf("Forcing measure() since mMaxPanelHeight=" + mMaxPanelHeight);
measure(MeasureSpec.makeMeasureSpec(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY));
}
- return mFullHeight;
+ return mMaxPanelHeight;
}
public void setExpandedFraction(float frac) {
@@ -621,7 +733,7 @@
}
frac = 0;
}
- setExpandedHeight(getFullHeight() * frac);
+ setExpandedHeight(getMaxPanelHeight() * frac);
}
public float getExpandedHeight() {
@@ -633,7 +745,7 @@
}
public boolean isFullyExpanded() {
- return mExpandedHeight >= getFullHeight();
+ return mExpandedHeight >= getMaxPanelHeight();
}
public boolean isFullyCollapsed() {
@@ -681,12 +793,12 @@
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println(String.format("[PanelView(%s): expandedHeight=%f fullHeight=%f closing=%s"
+ pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%f closing=%s"
+ " tracking=%s rubberbanding=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s"
+ "]",
this.getClass().getSimpleName(),
getExpandedHeight(),
- getFullHeight(),
+ getMaxPanelHeight(),
mClosing?"T":"f",
mTracking?"T":"f",
mRubberbanding?"T":"f",
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 60ec787..4730f2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -80,7 +80,6 @@
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.ScrollView;
import android.widget.TextView;
import com.android.internal.statusbar.StatusBarIcon;
@@ -94,16 +93,17 @@
import com.android.systemui.statusbar.NotificationData.Entry;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.StatusBarIconView;
+
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.DateView;
import com.android.systemui.statusbar.policy.HeadsUpNotificationView;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.NotificationRowLayout;
-import com.android.systemui.statusbar.policy.OnSizeChangedListener;
import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -169,7 +169,7 @@
Display mDisplay;
Point mCurrentDisplaySize = new Point();
private float mHeadsUpVerticalOffset;
- private int[] mPilePosition = new int[2];
+ private int[] mStackScrollerPosition = new int[2];
StatusBarWindowView mStatusBarWindow;
PhoneStatusBarView mStatusBarView;
@@ -195,7 +195,6 @@
// expanded notifications
NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
- ScrollView mScrollView;
View mExpandedContents;
int mNotificationPanelGravity;
int mNotificationPanelMarginBottomPx, mNotificationPanelMarginPx;
@@ -347,18 +346,18 @@
}
}};
+ private Runnable mOnFlipRunnable;
+
+ public void setOnFlipRunnable(Runnable onFlipRunnable) {
+ mOnFlipRunnable = onFlipRunnable;
+ }
+
@Override
public void setZenMode(int mode) {
super.setZenMode(mode);
if (mModeIcon == null) return;
if (!isDeviceProvisioned()) return;
- final boolean limited = mode == Settings.Global.ZEN_MODE_LIMITED;
- final boolean full = mode == Settings.Global.ZEN_MODE_FULL;
- mModeIcon.setVisibility(full || limited ? View.VISIBLE : View.GONE);
- final int icon = limited ? R.drawable.stat_sys_zen_limited : R.drawable.stat_sys_zen_full;
- if (full || limited) {
- mModeIcon.setImageResource(icon);
- }
+ mModeIcon.setVisibility(mode != Settings.Global.ZEN_MODE_OFF ? View.VISIBLE : View.GONE);
}
@Override
@@ -420,7 +419,8 @@
PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);
mStatusBarView.setPanelHolder(holder);
- mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(R.id.notification_panel);
+ mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(
+ R.id.notification_panel);
mNotificationPanel.setStatusBar(this);
mNotificationPanelIsFullScreenWidth =
(mNotificationPanel.getLayoutParams().width == ViewGroup.LayoutParams.MATCH_PARENT);
@@ -446,7 +446,8 @@
mHeadsUpNotificationView.setBar(this);
}
if (MULTIUSER_DEBUG) {
- mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(R.id.header_debug_info);
+ mNotificationPanelDebugText = (TextView) mNotificationPanel.findViewById(
+ R.id.header_debug_info);
mNotificationPanelDebugText.setVisibility(View.VISIBLE);
}
@@ -481,13 +482,15 @@
mMoreIcon = mStatusBarView.findViewById(R.id.moreIcon);
mNotificationIcons.setOverflowIndicator(mMoreIcon);
mModeIcon = (ImageView)mStatusBarView.findViewById(R.id.modeIcon);
+ mModeIcon.setImageResource(R.drawable.stat_sys_zen_limited);
mStatusBarContents = (LinearLayout)mStatusBarView.findViewById(R.id.status_bar_contents);
mTickerView = mStatusBarView.findViewById(R.id.ticker);
- mPile = (NotificationRowLayout)mStatusBarWindow.findViewById(R.id.latestItems);
- mPile.setLayoutTransitionsEnabled(false);
- mPile.setLongPressListener(getNotificationLongClicker());
- mExpandedContents = mPile; // was: expanded.findViewById(R.id.notificationLinearLayout);
+ mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
+ R.id.notification_stack_scroller);
+ mStackScroller.setLongPressListener(getNotificationLongClicker());
+
+ mExpandedContents = mStackScroller;
mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header);
@@ -530,16 +533,15 @@
}
}
if (mHasFlipSettings) {
- mNotificationButton = (ImageView) mStatusBarWindow.findViewById(R.id.notification_button);
+ mNotificationButton = (ImageView) mStatusBarWindow.findViewById(
+ R.id.notification_button);
if (mNotificationButton != null) {
mNotificationButton.setOnClickListener(mNotificationButtonListener);
}
}
- mScrollView = (ScrollView)mStatusBarWindow.findViewById(R.id.scroll);
- mScrollView.setVerticalScrollBarEnabled(false); // less drawing during pulldowns
if (!mNotificationPanelIsFullScreenWidth) {
- mScrollView.setSystemUiVisibility(
+ mNotificationPanel.setSystemUiVisibility(
View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS |
View.STATUS_BAR_DISABLE_CLOCK);
}
@@ -574,17 +576,18 @@
if (isAPhone) {
mEmergencyCallLabel =
(TextView) mStatusBarWindow.findViewById(R.id.emergency_calls_only);
- if (mEmergencyCallLabel != null) {
- mNetworkController.addEmergencyLabelView(mEmergencyCallLabel);
- mEmergencyCallLabel.setOnClickListener(new View.OnClickListener() {
- public void onClick(View v) { }});
- mEmergencyCallLabel.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- updateCarrierLabelVisibility(false);
- }});
- }
+ // TODO: Uncomment when correctly positioned
+// if (mEmergencyCallLabel != null) {
+// mNetworkController.addEmergencyLabelView(mEmergencyCallLabel);
+// mEmergencyCallLabel.setOnClickListener(new View.OnClickListener() {
+// public void onClick(View v) { }});
+// mEmergencyCallLabel.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+// @Override
+// public void onLayoutChange(View v, int left, int top, int right, int bottom,
+// int oldLeft, int oldTop, int oldRight, int oldBottom) {
+// updateCarrierLabelVisibility(false);
+// }});
+// }
}
mCarrierLabel = (TextView)mStatusBarWindow.findViewById(R.id.carrier_label);
@@ -602,12 +605,12 @@
}
// set up the dynamic hide/show of the label
- mPile.setOnSizeChangedListener(new OnSizeChangedListener() {
- @Override
- public void onSizeChanged(View view, int w, int h, int oldw, int oldh) {
- updateCarrierLabelVisibility(false);
- }
- });
+ // TODO: uncomment, handle this for the Stack scroller aswell
+// ((NotificationRowLayout) mStackScroller)
+// .setOnSizeChangedListener(new OnSizeChangedListener() {
+// @Override
+// public void onSizeChanged(View view, int w, int h, int oldw, int oldh) {
+// updateCarrierLabelVisibility(false);
}
// Quick Settings (where available, some restrictions apply)
@@ -981,9 +984,9 @@
@Override
public void resetHeadsUpDecayTimer() {
+ mHandler.removeMessages(MSG_HIDE_HEADS_UP);
if (mUseHeadsUp && mHeadsUpNotificationDecay > 0
&& mHeadsUpNotificationView.isClearable()) {
- mHandler.removeMessages(MSG_HIDE_HEADS_UP);
mHandler.sendEmptyMessageDelayed(MSG_HIDE_HEADS_UP, mHeadsUpNotificationDecay);
}
}
@@ -1046,7 +1049,7 @@
}
private void loadNotificationShade() {
- if (mPile == null) return;
+ if (mStackScroller == null) return;
int N = mNotificationData.size();
@@ -1058,8 +1061,8 @@
Entry ent = mNotificationData.get(N-i-1);
if (!(provisioned || showNotificationEvenIfUnprovisioned(ent.notification))) continue;
- // TODO How do we want to badge notifcations from related users.
- if (!notificationIsForCurrentOrRelatedUser(ent.notification)) continue;
+ // TODO How do we want to badge notifcations from profiles.
+ if (!notificationIsForCurrentProfiles(ent.notification)) continue;
final int vis = ent.notification.getNotification().visibility;
if (vis != Notification.VISIBILITY_SECRET) {
@@ -1072,21 +1075,21 @@
}
ArrayList<View> toRemove = new ArrayList<View>();
- for (int i=0; i<mPile.getChildCount(); i++) {
- View child = mPile.getChildAt(i);
+ for (int i=0; i< mStackScroller.getChildCount(); i++) {
+ View child = mStackScroller.getChildAt(i);
if (!toShow.contains(child)) {
toRemove.add(child);
}
}
for (View remove : toRemove) {
- mPile.removeView(remove);
+ mStackScroller.removeView(remove);
}
for (int i=0; i<toShow.size(); i++) {
View v = toShow.get(i);
if (v.getParent() == null) {
- mPile.addView(v, i);
+ mStackScroller.addView(v, i);
}
}
@@ -1118,7 +1121,7 @@
Entry ent = mNotificationData.get(N-i-1);
if (!((provisioned && ent.notification.getScore() >= HIDE_ICONS_BELOW_SCORE)
|| showNotificationEvenIfUnprovisioned(ent.notification))) continue;
- if (!notificationIsForCurrentOrRelatedUser(ent.notification)) continue;
+ if (!notificationIsForCurrentProfiles(ent.notification)) continue;
if (isLockscreenPublicMode()
&& ent.notification.getNotification().visibility
== Notification.VISIBILITY_SECRET
@@ -1153,19 +1156,22 @@
}
protected void updateCarrierLabelVisibility(boolean force) {
+ // TODO: Handle this for the notification stack scroller as well
if (!mShowCarrierInPanel) return;
// The idea here is to only show the carrier label when there is enough room to see it,
// i.e. when there aren't enough notifications to fill the panel.
if (SPEW) {
- Log.d(TAG, String.format("pileh=%d scrollh=%d carrierh=%d",
- mPile.getHeight(), mScrollView.getHeight(), mCarrierLabelHeight));
+ Log.d(TAG, String.format("stackScrollerh=%d scrollh=%d carrierh=%d",
+ mStackScroller.getHeight(), mStackScroller.getHeight(),
+ mCarrierLabelHeight));
}
final boolean emergencyCallsShownElsewhere = mEmergencyCallLabel != null;
final boolean makeVisible =
!(emergencyCallsShownElsewhere && mNetworkController.isEmergencyOnly())
- && mPile.getHeight() < (mNotificationPanel.getHeight() - mCarrierLabelHeight - mNotificationHeaderHeight)
- && mScrollView.getVisibility() == View.VISIBLE;
+ && mStackScroller.getHeight() < (mNotificationPanel.getHeight()
+ - mCarrierLabelHeight - mNotificationHeaderHeight)
+ && mStackScroller.getVisibility() == View.VISIBLE;
if (force || mCarrierLabelVisible != makeVisible) {
mCarrierLabelVisible = makeVisible;
@@ -1208,7 +1214,7 @@
if (mHasFlipSettings
&& mFlipSettingsView != null
&& mFlipSettingsView.getVisibility() == View.VISIBLE
- && mScrollView.getVisibility() != View.VISIBLE) {
+ && mStackScroller.getVisibility() != View.VISIBLE) {
// the flip settings panel is unequivocally showing; we should not be shown
mClearButton.setVisibility(View.INVISIBLE);
} else if (mClearButton.isShown()) {
@@ -1462,7 +1468,6 @@
}
mExpandedVisible = true;
- mPile.setLayoutTransitionsEnabled(true);
if (mNavigationBarView != null)
mNavigationBarView.setSlippery(true);
@@ -1577,7 +1582,7 @@
}
mNotificationPanel.expand();
- if (mHasFlipSettings && mScrollView.getVisibility() != View.VISIBLE) {
+ if (mHasFlipSettings && mStackScroller.getVisibility() != View.VISIBLE) {
flipToNotifications();
}
@@ -1591,11 +1596,11 @@
if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
if (mClearButtonAnim != null) mClearButtonAnim.cancel();
- mScrollView.setVisibility(View.VISIBLE);
+ mStackScroller.setVisibility(View.VISIBLE);
mScrollViewAnim = start(
startDelay(FLIP_DURATION_OUT,
interpolator(mDecelerateInterpolator,
- ObjectAnimator.ofFloat(mScrollView, View.SCALE_X, 0f, 1f)
+ ObjectAnimator.ofFloat(mStackScroller, View.SCALE_X, 0f, 1f)
.setDuration(FLIP_DURATION_IN)
)));
mFlipSettingsViewAnim = start(
@@ -1622,6 +1627,9 @@
updateCarrierLabelVisibility(false);
}
}, FLIP_DURATION - 150);
+ if (mOnFlipRunnable != null) {
+ mOnFlipRunnable.run();
+ }
}
@Override
@@ -1653,11 +1661,21 @@
mFlipSettingsView.setScaleX(1f);
mFlipSettingsView.setVisibility(View.VISIBLE);
mSettingsButton.setVisibility(View.GONE);
- mScrollView.setVisibility(View.GONE);
- mScrollView.setScaleX(0f);
+ mStackScroller.setVisibility(View.GONE);
+ mStackScroller.setScaleX(0f);
mNotificationButton.setVisibility(View.VISIBLE);
mNotificationButton.setAlpha(1f);
mClearButton.setVisibility(View.GONE);
+ if (mOnFlipRunnable != null) {
+ mOnFlipRunnable.run();
+ }
+ }
+
+ public boolean isFlippedToSettings() {
+ if (mFlipSettingsView != null) {
+ return mFlipSettingsView.getVisibility() == View.VISIBLE;
+ }
+ return false;
}
public void flipToSettings() {
@@ -1681,15 +1699,15 @@
mScrollViewAnim = start(
setVisibilityWhenDone(
interpolator(mAccelerateInterpolator,
- ObjectAnimator.ofFloat(mScrollView, View.SCALE_X, 1f, 0f)
+ ObjectAnimator.ofFloat(mStackScroller, View.SCALE_X, 1f, 0f)
)
.setDuration(FLIP_DURATION_OUT),
- mScrollView, View.INVISIBLE));
+ mStackScroller, View.INVISIBLE));
mSettingsButtonAnim = start(
setVisibilityWhenDone(
ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f)
.setDuration(FLIP_DURATION),
- mScrollView, View.INVISIBLE));
+ mStackScroller, View.INVISIBLE));
mNotificationButton.setVisibility(View.VISIBLE);
mNotificationButtonAnim = start(
ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f)
@@ -1704,6 +1722,9 @@
updateCarrierLabelVisibility(false);
}
}, FLIP_DURATION - 150);
+ if (mOnFlipRunnable != null) {
+ mOnFlipRunnable.run();
+ }
}
public void flipPanels() {
@@ -1743,8 +1764,8 @@
if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
if (mClearButtonAnim != null) mClearButtonAnim.cancel();
- mScrollView.setScaleX(1f);
- mScrollView.setVisibility(View.VISIBLE);
+ mStackScroller.setScaleX(1f);
+ mStackScroller.setVisibility(View.VISIBLE);
mSettingsButton.setAlpha(1f);
mSettingsButton.setVisibility(View.VISIBLE);
mNotificationPanel.setVisibility(View.GONE);
@@ -1754,7 +1775,6 @@
}
mExpandedVisible = false;
- mPile.setLayoutTransitionsEnabled(false);
if (mNavigationBarView != null)
mNavigationBarView.setSlippery(false);
visibilityChanged(false);
@@ -1781,53 +1801,6 @@
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
}
- /**
- * Enables or disables layers on the children of the notifications pile.
- *
- * When layers are enabled, this method attempts to enable layers for the minimal
- * number of children. Only children visible when the notification area is fully
- * expanded will receive a layer. The technique used in this method might cause
- * more children than necessary to get a layer (at most one extra child with the
- * current UI.)
- *
- * @param layerType {@link View#LAYER_TYPE_NONE} or {@link View#LAYER_TYPE_HARDWARE}
- */
- private void setPileLayers(int layerType) {
- final int count = mPile.getChildCount();
-
- switch (layerType) {
- case View.LAYER_TYPE_NONE:
- for (int i = 0; i < count; i++) {
- mPile.getChildAt(i).setLayerType(layerType, null);
- }
- break;
- case View.LAYER_TYPE_HARDWARE:
- final int[] location = new int[2];
- mNotificationPanel.getLocationInWindow(location);
-
- final int left = location[0];
- final int top = location[1];
- final int right = left + mNotificationPanel.getWidth();
- final int bottom = top + getExpandedViewMaxHeight();
-
- final Rect childBounds = new Rect();
-
- for (int i = 0; i < count; i++) {
- final View view = mPile.getChildAt(i);
- view.getLocationInWindow(location);
-
- childBounds.set(location[0], location[1],
- location[0] + view.getWidth(), location[1] + view.getHeight());
-
- if (childBounds.intersects(left, top, right, bottom)) {
- view.setLayerType(layerType, null);
- }
- }
-
- break;
- }
- }
-
public boolean interceptTouchEvent(MotionEvent event) {
if (DEBUG_GESTURES) {
if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
@@ -2125,7 +2098,7 @@
if (!isDeviceProvisioned()) return;
// not for you
- if (!notificationIsForCurrentOrRelatedUser(n)) return;
+ if (!notificationIsForCurrentProfiles(n)) return;
// Show the ticker if one is requested. Also don't do this
// until status bar window is attached to the window manager,
@@ -2205,10 +2178,11 @@
pw.println(" mTicking=" + mTicking);
pw.println(" mTracking=" + mTracking);
pw.println(" mDisplayMetrics=" + mDisplayMetrics);
- pw.println(" mPile: " + viewInfo(mPile));
+ pw.println(" mStackScroller: " + viewInfo(mStackScroller));
pw.println(" mTickerView: " + viewInfo(mTickerView));
- pw.println(" mScrollView: " + viewInfo(mScrollView)
- + " scroll " + mScrollView.getScrollX() + "," + mScrollView.getScrollY());
+ pw.println(" mStackScroller: " + viewInfo(mStackScroller)
+ + " scroll " + mStackScroller.getScrollX()
+ + "," + mStackScroller.getScrollY());
}
pw.print(" mInteractingWindows="); pw.println(mInteractingWindows);
@@ -2383,8 +2357,8 @@
if (ENABLE_HEADS_UP && mHeadsUpNotificationView != null) {
mHeadsUpNotificationView.setMargin(mNotificationPanelMarginPx);
- mPile.getLocationOnScreen(mPilePosition);
- mHeadsUpVerticalOffset = mPilePosition[1] - mNaturalBarHeight;
+ mStackScroller.getLocationOnScreen(mStackScrollerPosition);
+ mHeadsUpVerticalOffset = mStackScrollerPosition[1] - mNaturalBarHeight;
}
updateCarrierLabelVisibility(false);
@@ -2403,77 +2377,21 @@
private View.OnClickListener mClearButtonListener = new View.OnClickListener() {
public void onClick(View v) {
synchronized (mNotificationData) {
- // animate-swipe all dismissable notifications, then animate the shade closed
- int numChildren = mPile.getChildCount();
-
- int scrollTop = mScrollView.getScrollY();
- int scrollBottom = scrollTop + mScrollView.getHeight();
- final ArrayList<View> snapshot = new ArrayList<View>(numChildren);
- for (int i=0; i<numChildren; i++) {
- final View child = mPile.getChildAt(i);
- if (mPile.canChildBeDismissed(child) && child.getBottom() > scrollTop &&
- child.getTop() < scrollBottom) {
- snapshot.add(child);
- }
- }
- if (snapshot.isEmpty()) {
- animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
- return;
- }
- new Thread(new Runnable() {
+ mPostCollapseCleanup = new Runnable() {
@Override
public void run() {
- // Decrease the delay for every row we animate to give the sense of
- // accelerating the swipes
- final int ROW_DELAY_DECREMENT = 10;
- int currentDelay = 140;
- int totalDelay = 0;
-
- // Set the shade-animating state to avoid doing other work during
- // all of these animations. In particular, avoid layout and
- // redrawing when collapsing the shade.
- mPile.setViewRemoval(false);
-
- mPostCollapseCleanup = new Runnable() {
- @Override
- public void run() {
- if (DEBUG) {
- Log.v(TAG, "running post-collapse cleanup");
- }
- try {
- mPile.setViewRemoval(true);
- mBarService.onClearAllNotifications(mCurrentUserId);
- } catch (Exception ex) { }
- }
- };
-
- View sampleView = snapshot.get(0);
- int width = sampleView.getWidth();
- final int dir = sampleView.isLayoutRtl() ? -1 : +1;
- final int velocity = dir * width * 8; // 1000/8 = 125 ms duration
- for (final View _v : snapshot) {
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- mPile.dismissRowAnimated(_v, velocity);
- }
- }, totalDelay);
- currentDelay = Math.max(50, currentDelay - ROW_DELAY_DECREMENT);
- totalDelay += currentDelay;
+ if (DEBUG) {
+ Log.v(TAG, "running post-collapse cleanup");
}
- // Delay the collapse animation until after all swipe animations have
- // finished. Provide some buffer because there may be some extra delay
- // before actually starting each swipe animation. Ideally, we'd
- // synchronize the end of those animations with the start of the collaps
- // exactly.
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
- }
- }, totalDelay + 225);
+ try {
+ mBarService.onClearAllNotifications(mCurrentUserId);
+ } catch (Exception ex) { }
}
- }).start();
+ };
+
+ animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
+ return;
+ // TODO: Handle this better with notification stack scroller
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index 8170b5a..d67f7cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -33,6 +33,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
@@ -42,6 +43,7 @@
import android.media.MediaRouter;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
+import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -56,11 +58,13 @@
import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
+import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.view.WindowManager.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
@@ -897,7 +901,17 @@
d.requestWindowFeature(Window.FEATURE_NO_TITLE);
d.setCancelable(true);
d.setCanceledOnTouchOutside(true);
- final ZenModeView v = new ZenModeView(mContext);
+ final ZenModeView v = new ZenModeView(mContext) {
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ WindowManager.LayoutParams lp = d.getWindow().getAttributes();
+ lp.width = mContext.getResources()
+ .getDimensionPixelSize(R.dimen.zen_mode_dialog_width);
+ d.getWindow().setAttributes(lp);
+ }
+ };
+ v.setAutoActivate(true);
v.setAdapter(new ZenModeViewAdapter(mContext) {
@Override
public void configure() {
@@ -914,6 +928,9 @@
d.setContentView(v);
d.create();
d.getWindow().setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
+ WindowManager.LayoutParams lp = d.getWindow().getAttributes();
+ lp.width = mContext.getResources().getDimensionPixelSize(R.dimen.zen_mode_dialog_width);
+ d.getWindow().setAttributes(lp);
d.show();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index c3c281c..9b25046 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -608,16 +608,8 @@
Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
mZenModeState.enabled = mode != Settings.Global.ZEN_MODE_OFF;
mZenModeState.zenMode = mode;
- if (mode == Settings.Global.ZEN_MODE_FULL) {
- mZenModeState.iconId = R.drawable.stat_sys_zen_full;
- mZenModeState.label = ZenModeView.modeToLabel(ZenModeView.Adapter.MODE_FULL);
- } else if (mode == Settings.Global.ZEN_MODE_LIMITED) {
- mZenModeState.iconId = R.drawable.stat_sys_zen_limited;
- mZenModeState.label = ZenModeView.modeToLabel(ZenModeView.Adapter.MODE_LIMITED);
- } else {
- mZenModeState.iconId = R.drawable.stat_sys_zen_limited;
- mZenModeState.label = ZenModeView.modeToLabel(ZenModeView.Adapter.MODE_LIMITED);
- }
+ mZenModeState.label = ZenModeView.MODE_LABEL;
+ mZenModeState.iconId = R.drawable.stat_sys_zen_limited;
mZenModeCallback.refreshView(mZenModeTile, mZenModeState);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 7b03195..a7121c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -26,12 +26,12 @@
import android.view.View;
import android.view.ViewRootImpl;
import android.widget.FrameLayout;
-import android.widget.ScrollView;
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.statusbar.BaseStatusBar;
-import com.android.systemui.statusbar.policy.NotificationRowLayout;
+import com.android.systemui.statusbar.policy.ScrollAdapter;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
public class StatusBarWindowView extends FrameLayout
@@ -40,9 +40,8 @@
public static final boolean DEBUG = BaseStatusBar.DEBUG;
private ExpandHelper mExpandHelper;
- private NotificationRowLayout latestItems;
+ private NotificationStackScrollLayout mStackScrollLayout;
private NotificationPanelView mNotificationPanel;
- private ScrollView mScrollView;
PhoneStatusBar mService;
@@ -55,14 +54,16 @@
@Override
protected void onAttachedToWindow () {
super.onAttachedToWindow();
- latestItems = (NotificationRowLayout) findViewById(R.id.latestItems);
- mScrollView = (ScrollView) findViewById(R.id.scroll);
+
+ mStackScrollLayout = (NotificationStackScrollLayout) findViewById(
+ R.id.notification_stack_scroller);
mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_min_height);
int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height);
- mExpandHelper = new ExpandHelper(getContext(), latestItems, minHeight, maxHeight);
+ mExpandHelper = new ExpandHelper(getContext(), mStackScrollLayout,
+ minHeight, maxHeight);
mExpandHelper.setEventSource(this);
- mExpandHelper.setScrollView(mScrollView);
+ mExpandHelper.setScrollAdapter(mStackScrollLayout);
// We really need to be able to animate while window animations are going on
// so that activities may be started asynchronously from panel animations
@@ -88,7 +89,8 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercept = false;
- if (mNotificationPanel.isFullyExpanded() && mScrollView.getVisibility() == View.VISIBLE) {
+ if (mNotificationPanel.isFullyExpanded()
+ && mStackScrollLayout.getVisibility() == View.VISIBLE) {
intercept = mExpandHelper.onInterceptTouchEvent(ev);
}
if (!intercept) {
@@ -97,7 +99,7 @@
if (intercept) {
MotionEvent cancellation = MotionEvent.obtain(ev);
cancellation.setAction(MotionEvent.ACTION_CANCEL);
- latestItems.onInterceptTouchEvent(cancellation);
+ mStackScrollLayout.onInterceptTouchEvent(cancellation);
cancellation.recycle();
}
return intercept;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
index d1c7a41..49cf78b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
@@ -16,15 +16,12 @@
package com.android.systemui.statusbar.phone;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
-import android.graphics.Paint;
-import android.graphics.Path;
+import android.graphics.PorterDuff.Mode;
import android.graphics.Typeface;
import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.shapes.PathShape;
+import android.graphics.drawable.shapes.OvalShape;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextPaint;
@@ -36,45 +33,46 @@
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
-import android.widget.ImageView;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.FrameLayout;
import android.widget.LinearLayout;
-import android.widget.ListView;
import android.widget.RelativeLayout;
-import android.widget.Spinner;
+import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
-import com.android.systemui.R;
import com.android.systemui.statusbar.phone.ZenModeView.Adapter.ExitCondition;
public class ZenModeView extends RelativeLayout {
private static final String TAG = ZenModeView.class.getSimpleName();
private static final boolean DEBUG = false;
+ public static final String MODE_LABEL = "Limited interruptions";
+ public static final int BACKGROUND = 0xff282828;
+
private static final Typeface CONDENSED =
Typeface.create("sans-serif-condensed", Typeface.NORMAL);
private static final int GRAY = 0xff999999; //TextAppearance.StatusBar.Expanded.Network
- private static final int BACKGROUND = 0xff282828;
- private static final long DURATION = new ValueAnimator().getDuration();
- private static final long BOUNCE_DURATION = DURATION / 3;
- private static final float BOUNCE_SCALE = 0.8f;
- private static final float SETTINGS_ALPHA = 0.6f;
+ private static final int DARK_GRAY = 0xff333333;
- private static final String FULL_TEXT =
- "You won't hear any calls, alarms or timers.";
+ private static final long DURATION = new ValueAnimator().getDuration();
+ private static final long PAGER_DURATION = DURATION / 2;
+ private static final long CLOSE_DELAY = 600;
+ private static final long AUTO_ACTIVATE_DELAY = 100;
private final Context mContext;
- private final Paint mPathPaint;
- private final ImageView mSettingsButton;
- private final ModeSpinner mModeSpinner;
- private final TextView mActionButton;
+ private final TextView mModeText;
+ private final Switch mModeSwitch;
private final View mDivider;
private final UntilPager mUntilPager;
- private final AlarmWarning mAlarmWarning;
+ private final ProgressDots mProgressDots;
+ private final View mDivider2;
+ private final TextView mSettingsButton;
private Adapter mAdapter;
+ private boolean mInit;
+ private boolean mAutoActivate;
public ZenModeView(Context context) {
this(context, null);
@@ -88,54 +86,42 @@
final int iconSize = mContext.getResources()
.getDimensionPixelSize(com.android.internal.R.dimen.notification_large_icon_width);
final int topRowSize = iconSize * 2 / 3;
- final int p = topRowSize / 7;
+ final int p = topRowSize / 3;
- mPathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mPathPaint.setStyle(Paint.Style.STROKE);
- mPathPaint.setColor(GRAY);
- mPathPaint.setStrokeWidth(p / 2);
+ LayoutParams lp = null;
- mSettingsButton = new ImageView(mContext);
- mSettingsButton.setPadding(p, p, p, p);
- mSettingsButton.setImageResource(R.drawable.ic_notify_settings_normal);
- LayoutParams lp = new LayoutParams(topRowSize, topRowSize);
- lp.topMargin = p;
+ mModeText = new TextView(mContext);
+ mModeText.setText(MODE_LABEL);
+ mModeText.setId(android.R.id.title);
+ mModeText.setTextColor(GRAY);
+ mModeText.setTypeface(CONDENSED);
+ mModeText.setAllCaps(true);
+ mModeText.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
+ mModeText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mModeText.getTextSize() * 1.5f);
+ lp = new LayoutParams(LayoutParams.WRAP_CONTENT, topRowSize);
lp.leftMargin = p;
- addView(mSettingsButton, lp);
- mSettingsButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mAdapter != null && mAdapter.getMode() == Adapter.MODE_LIMITED) {
- mAdapter.configure();
- }
- bounce(mSettingsButton, null);
- }
- });
+ addView(mModeText, lp);
- mModeSpinner = new ModeSpinner(mContext);
- mModeSpinner.setId(android.R.id.title);
+ mModeSwitch = new Switch(mContext);
+ mModeSwitch.setSwitchPadding(0);
+ mModeSwitch.setSwitchTypeface(CONDENSED);
lp = new LayoutParams(LayoutParams.WRAP_CONTENT, topRowSize);
lp.topMargin = p;
- lp.addRule(CENTER_HORIZONTAL);
- addView(mModeSpinner, lp);
-
- mActionButton = new TextView(mContext);
- mActionButton.setTextColor(GRAY);
- mActionButton.setTypeface(CONDENSED);
- mActionButton.setTextSize(TypedValue.COMPLEX_UNIT_PX, mActionButton.getTextSize() * 1.2f);
- mActionButton.setAllCaps(true);
- mActionButton.setGravity(Gravity.CENTER);
- mActionButton.setPadding(p, 0, p * 2, 0);
- lp = new LayoutParams(LayoutParams.WRAP_CONTENT, topRowSize);
- lp.topMargin = p;
+ lp.rightMargin = p;
lp.addRule(ALIGN_PARENT_RIGHT);
- lp.addRule(ALIGN_BASELINE, mModeSpinner.getId());
- addView(mActionButton, lp);
- mActionButton.setOnClickListener(new View.OnClickListener() {
+ lp.addRule(ALIGN_BASELINE, mModeText.getId());
+ addView(mModeSwitch, lp);
+ mModeSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
- public void onClick(View v) {
- bounce(v, null);
- beginOrEnd();
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ mAdapter.setMode(isChecked);
+ if (!mInit) return;
+ postDelayed(new Runnable(){
+ @Override
+ public void run() {
+ mAdapter.close();
+ }
+ }, CLOSE_DELAY);
}
});
@@ -143,35 +129,54 @@
mDivider.setId(android.R.id.empty);
mDivider.setBackgroundColor(GRAY);
lp = new LayoutParams(LayoutParams.MATCH_PARENT, 2);
- lp.addRule(BELOW, mModeSpinner.getId());
- lp.topMargin = p;
+ lp.addRule(BELOW, mModeText.getId());
lp.bottomMargin = p;
addView(mDivider, lp);
- mUntilPager = new UntilPager(mContext, mPathPaint, iconSize * 3 / 4);
+ mUntilPager = new UntilPager(mContext, iconSize * 3 / 4);
mUntilPager.setId(android.R.id.tabhost);
- lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ lp.leftMargin = lp.rightMargin = iconSize / 2;
+ lp.addRule(CENTER_HORIZONTAL);
lp.addRule(BELOW, mDivider.getId());
addView(mUntilPager, lp);
- mAlarmWarning = new AlarmWarning(mContext);
+ mProgressDots = new ProgressDots(mContext, iconSize / 5);
+ mProgressDots.setId(android.R.id.progress);
lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.addRule(CENTER_HORIZONTAL);
lp.addRule(BELOW, mUntilPager.getId());
- lp.bottomMargin = p;
- addView(mAlarmWarning, lp);
- }
+ addView(mProgressDots, lp);
- private void beginOrEnd() {
- if (mAdapter == null) return;
- if (mAdapter.getMode() == mAdapter.getCommittedMode()) {
- // end
- mAdapter.setCommittedMode(Adapter.MODE_OFF);
- } else {
- // begin
- mAdapter.setCommittedMode(mAdapter.getMode());
- }
- mAdapter.close();
+ mDivider2 = new View(mContext);
+ mDivider2.setId(android.R.id.widget_frame);
+ mDivider2.setBackgroundColor(GRAY);
+ lp = new LayoutParams(LayoutParams.MATCH_PARENT, 2);
+ lp.addRule(BELOW, mProgressDots.getId());
+ addView(mDivider2, lp);
+
+ mSettingsButton = new TextView(mContext);
+ mSettingsButton.setTypeface(CONDENSED);
+ mSettingsButton.setTextSize(TypedValue.COMPLEX_UNIT_PX, mSettingsButton.getTextSize() * 1.3f);
+ mSettingsButton.setPadding(p, p, p, p);
+ mSettingsButton.setText("More settings...");
+ lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ lp.addRule(BELOW, mDivider2.getId());
+ addView(mSettingsButton, lp);
+ mSettingsButton.setOnTouchListener(new OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ mSettingsButton.setBackgroundColor(DARK_GRAY);
+ } else if (event.getAction() == MotionEvent.ACTION_UP) {
+ mSettingsButton.setBackground(null);
+ if (mAdapter != null) {
+ mAdapter.configure();
+ }
+ }
+ return true;
+ }
+ });
}
public void setAdapter(Adapter adapter) {
@@ -190,185 +195,54 @@
updateState(false);
}
- private void updateState(boolean animate) {
- mModeSpinner.updateState();
- mUntilPager.updateState();
- mAlarmWarning.updateState(animate);
- final float settingsAlpha = isFull() ? 0 : SETTINGS_ALPHA;
- if (settingsAlpha != mSettingsButton.getAlpha()) {
- if (animate) {
- mSettingsButton.animate().alpha(settingsAlpha).start();
- } else {
- mSettingsButton.setAlpha(settingsAlpha);
- }
- }
- final boolean committed = mAdapter != null
- && mAdapter.getMode() == mAdapter.getCommittedMode();
- mActionButton.setText(committed ? "End" : "Begin");
- }
-
- private boolean isFull() {
- return mAdapter != null && mAdapter.getMode() == Adapter.MODE_FULL;
- }
-
@Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (DEBUG) log("onMeasure %s %s",
- MeasureSpec.toString(widthMeasureSpec), MeasureSpec.toString(heightMeasureSpec));
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- if (!isFull()) {
- final LayoutParams lp = (LayoutParams) mModeSpinner.getLayoutParams();
- final int mh = vh(mModeSpinner) + vh(mDivider) + vh(mUntilPager) + lp.topMargin;
- setMeasuredDimension(getMeasuredWidth(), mh);
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ if (mAutoActivate) {
+ mAutoActivate = false;
+ postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ if (!mModeSwitch.isChecked()) {
+ mInit = false;
+ mModeSwitch.setChecked(true);
+ }
+ }
+ }, AUTO_ACTIVATE_DELAY);
}
}
- private int vh(View v) {
- LayoutParams lp = (LayoutParams) v.getLayoutParams();
- return v.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
+ public void setAutoActivate(boolean value) {
+ mAutoActivate = value;
+ }
+
+ private void updateState(boolean animate) {
+ mUntilPager.updateState();
+ mModeSwitch.setChecked(mAdapter.getMode());
+ mInit = true;
}
private static void log(String msg, Object... args) {
Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args));
}
- private static ShapeDrawable sd(Path p, int size, Paint pt) {
- final ShapeDrawable sd = new ShapeDrawable(new PathShape(p, size, size));
- sd.getPaint().set(pt);
- sd.setIntrinsicHeight(size);
- sd.setIntrinsicWidth(size);
- return sd;
- }
+ private final class UntilView extends FrameLayout {
+ private static final boolean SUPPORT_LINKS = false;
- private static void bounce(final View v, final Runnable midBounce) {
- v.animate().scaleX(BOUNCE_SCALE).scaleY(BOUNCE_SCALE).setDuration(DURATION / 3)
- .setListener(new AnimatorListenerAdapter() {
- private boolean mFired;
- @Override
- public void onAnimationEnd(Animator animation) {
- if (!mFired) {
- mFired = true;
- if (midBounce != null) {
- midBounce.run();
- }
- v.animate().scaleX(1).scaleY(1).setListener(null).start();
- }
- }
- }).start();
- }
-
- public static String modeToString(int mode) {
- if (mode == Adapter.MODE_OFF) return "MODE_OFF";
- if (mode == Adapter.MODE_LIMITED) return "MODE_LIMITED";
- if (mode == Adapter.MODE_FULL) return "MODE_FULL";
- throw new IllegalArgumentException("Invalid mode: " + mode);
- }
-
- public static String modeToLabel(int mode) {
- if (mode == Adapter.MODE_LIMITED) return "Limited interruptions";
- if (mode == Adapter.MODE_FULL) return "Zero interruptions";
- throw new UnsupportedOperationException("Unsupported mode: " + mode);
- }
-
- private final class UntilPager extends RelativeLayout {
- private final ImageView mPrev;
- private final ImageView mNext;
- private final TextView mText1;
- private final TextView mText2;
-
- private TextView mText;
-
- public UntilPager(Context context, Paint pathPaint, int iconSize) {
+ private final TextView mText;
+ public UntilView(Context context) {
super(context);
- mText1 = new TextView(mContext);
- mText1.setTextSize(TypedValue.COMPLEX_UNIT_PX, mText1.getTextSize() * 1.2f);
- mText1.setTypeface(CONDENSED);
- mText1.setTextColor(GRAY);
- mText1.setGravity(Gravity.CENTER);
- LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, iconSize);
- addView(mText1, lp);
- mText = mText1;
-
- mText2 = new TextView(mContext);
- mText2.setTextSize(TypedValue.COMPLEX_UNIT_PX, mText1.getTextSize());
- mText2.setTypeface(CONDENSED);
- mText2.setTextColor(GRAY);
- mText2.setAlpha(0);
- mText2.setGravity(Gravity.CENTER);
- addView(mText2, lp);
-
- lp = new LayoutParams(iconSize, iconSize);
- final View v = new View(mContext);
- v.setBackgroundColor(BACKGROUND);
- addView(v, lp);
- mPrev = new ImageView(mContext);
- mPrev.setId(android.R.id.button1);
- mPrev.setImageDrawable(sd(prevPath(iconSize), iconSize, pathPaint));
- addView(mPrev, lp);
- mPrev.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- onNav(v, -1);
- }
- });
-
- lp = new LayoutParams(iconSize, iconSize);
- lp.addRule(ALIGN_PARENT_RIGHT);
- final View v2 = new View(mContext);
- v2.setBackgroundColor(BACKGROUND);
- addView(v2, lp);
- mNext = new ImageView(mContext);
- mNext.setId(android.R.id.button2);
- mNext.setImageDrawable(sd(nextPath(iconSize), iconSize, pathPaint));
- addView(mNext, lp);
- mNext.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- onNav(v, 1);
- }
- });
-
- updateState();
+ mText = new TextView(mContext);
+ mText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mText.getTextSize() * 1.3f);
+ mText.setTypeface(CONDENSED);
+ mText.setTextColor(GRAY);
+ mText.setGravity(Gravity.CENTER);
+ addView(mText);
}
- private void onNav(View v, int d) {
- bounce(v, null);
- if (mAdapter == null) {
- return;
- }
- if (mAdapter.getExitConditionCount() == 1) {
- horBounce(d);
- return;
- }
- final int w = getWidth();
- final float s = Math.signum(d);
- final TextView current = mText;
- final TextView other = mText == mText1 ? mText2 : mText1;
- final ExitCondition ec = mAdapter.getExitCondition(d);
- setText(other, ec);
- other.setTranslationX(-s * w);
- other.animate().translationX(0).alpha(1).setDuration(DURATION).start();
- current.animate().translationX(s * w).alpha(0).setDuration(DURATION).start();
- mText = other;
- mAdapter.select(ec);
- }
-
- private void horBounce(int d) {
- final int w = getWidth();
- mText.animate()
- .setDuration(BOUNCE_DURATION)
- .translationX(Math.signum(d) * w / 20)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mText.animate().translationX(0).setListener(null).start();
- }
- }).start();
- }
-
- private void setText(final TextView textView, final ExitCondition ec) {
+ public void setExitCondition(final ExitCondition ec) {
SpannableStringBuilder ss = new SpannableStringBuilder(ec.summary);
- if (ec.action != null) {
+ if (SUPPORT_LINKS && ec.action != null) {
ss.setSpan(new CustomLinkSpan() {
@Override
public void onClick() {
@@ -376,38 +250,122 @@
Toast.makeText(mContext, ec.action, Toast.LENGTH_SHORT).show();
}
}, 0, ss.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
- textView.setMovementMethod(LinkMovementMethod.getInstance());
+ mText.setMovementMethod(LinkMovementMethod.getInstance());
} else {
- textView.setMovementMethod(null);
+ mText.setMovementMethod(null);
}
- textView.setText(ss);
+ mText.setText(ss);
+ }
+ }
+
+ private final class ProgressDots extends LinearLayout {
+ private final int mDotSize;
+ public ProgressDots(Context context, int dotSize) {
+ super(context);
+ setOrientation(HORIZONTAL);
+ mDotSize = dotSize;
+ }
+
+ private void updateState(int current, int count) {
+ while (getChildCount() < count) {
+ View dot = new View(mContext);
+ OvalShape s = new OvalShape();
+ ShapeDrawable sd = new ShapeDrawable(s);
+
+ dot.setBackground(sd);
+ LayoutParams lp = new LayoutParams(mDotSize, mDotSize);
+ lp.leftMargin = lp.rightMargin = mDotSize / 2;
+ lp.topMargin = lp.bottomMargin = mDotSize * 2 / 3;
+ addView(dot, lp);
+ }
+ while (getChildCount() > count) {
+ removeViewAt(getChildCount() - 1);
+ }
+ final int N = getChildCount();
+ for (int i = 0; i < N; i++) {
+ final int color = current == i ? GRAY : DARK_GRAY;
+ ((ShapeDrawable)getChildAt(i).getBackground()).setColorFilter(color, Mode.ADD);
+ }
+ }
+ }
+
+ private final class UntilPager extends RelativeLayout {
+ private final UntilView[] mViews;
+ private int mCurrent;
+ private float mDownX;
+
+ public UntilPager(Context context, int iconSize) {
+ super(context);
+ mViews = new UntilView[3];
+ for (int i = 0; i < mViews.length; i++) {
+ UntilView v = new UntilView(mContext);
+ LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, iconSize);
+ addView(v, lp);
+ mViews[i] = v;
+ }
+ updateState();
+ addOnLayoutChangeListener(new OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right,
+ int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ if (left != oldLeft || right != oldRight) {
+ updateState();
+ }
+ }
+ });
+ setBackgroundColor(DARK_GRAY);
}
private void updateState() {
if (mAdapter == null) {
return;
}
- setText(mText, mAdapter.getExitCondition(0));
+ UntilView current = mViews[mCurrent];
+ current.setExitCondition(mAdapter.getExitCondition(0));
+ UntilView next = mViews[mCurrent + 1 % 3];
+ next.setExitCondition(mAdapter.getExitCondition(1));
+ UntilView prev = mViews[mCurrent + 2 % 3];
+ prev.setExitCondition(mAdapter.getExitCondition(-1));
+ position(0, false);
+ mProgressDots.updateState(mAdapter.getExitConditionIndex(),
+ mAdapter.getExitConditionCount());
}
- private Path prevPath(int size) {
- final int hp = size * 3 / 8;
- final int vp = size / 4;
- final Path p = new Path();
- p.moveTo(size - hp, vp);
- p.lineTo(hp, size / 2);
- p.lineTo(size - hp, size - vp);
- return p;
+ private void position(float dx, boolean animate) {
+ int w = getWidth();
+ UntilView current = mViews[mCurrent];
+ UntilView next = mViews[mCurrent + 1 % 3];
+ UntilView prev = mViews[mCurrent + 2 % 3];
+ if (animate) {
+ current.animate().setDuration(PAGER_DURATION).translationX(dx).start();
+ next.animate().setDuration(PAGER_DURATION).translationX(w + dx).start();
+ prev.animate().setDuration(PAGER_DURATION).translationX(-w + dx).start();
+ } else {
+ current.setTranslationX(dx);
+ next.setTranslationX(w + dx);
+ prev.setTranslationX(-w + dx);
+ }
}
- private Path nextPath(int size) {
- final int hp = size * 3 / 8;
- final int vp = size / 4;
- Path p = new Path();
- p.moveTo(hp, vp);
- p.lineTo(size - hp, size / 2);
- p.lineTo(hp, size - vp);
- return p;
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ log("onTouchEvent " + MotionEvent.actionToString(event.getAction()));
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ mDownX = event.getX();
+ } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
+ float dx = event.getX() - mDownX;
+ position(dx, false);
+ } else if (event.getAction() == MotionEvent.ACTION_UP
+ || event.getAction() == MotionEvent.ACTION_CANCEL) {
+ float dx = event.getX() - mDownX;
+ int d = Math.abs(dx) < getWidth() / 3 ? 0 : Math.signum(dx) > 0 ? -1 : 1;
+ if (d != 0 && mAdapter.getExitConditionCount() > 1) {
+ mAdapter.select(mAdapter.getExitCondition(d));
+ } else {
+ position(0, true);
+ }
+ }
+ return true;
}
}
@@ -432,21 +390,16 @@
}
public interface Adapter {
- public static final int MODE_OFF = 0;
- public static final int MODE_LIMITED = 1;
- public static final int MODE_FULL = 2;
-
void configure();
void close();
- int getMode();
- void setMode(int mode);
- int getCommittedMode();
- void setCommittedMode(int mode);
+ boolean getMode();
+ void setMode(boolean mode);
void select(ExitCondition ec);
void init();
void setCallbacks(Callbacks callbacks);
ExitCondition getExitCondition(int d);
int getExitConditionCount();
+ int getExitConditionIndex();
public static class ExitCondition {
public String summary;
@@ -459,110 +412,4 @@
void onChanged();
}
}
-
- private final class ModeSpinner extends Spinner {
- public ModeSpinner(final Context context) {
- super(context);
- setBackgroundResource(R.drawable.spinner_default_holo_dark_am_no_underline);
- final ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(mContext, 0) {
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (DEBUG) log("getView %s parent=%s", position, parent);
- return getDropDownView(position, convertView, parent);
- }
-
- @Override
- public View getDropDownView(final int position, View convertView, ViewGroup parent) {
- if (DEBUG) log("getDropDownView %s cv=%s parent=%s",
- position, convertView, parent);
- final TextView tv = convertView != null ? (TextView) convertView
- : new TextView(context);
- final int mode = getItem(position);
- tv.setText(modeToLabel(mode));
- final boolean inDropdown = parent instanceof ListView;
- if (convertView == null) {
- if (DEBUG) log(" setting up view");
- tv.setTextColor(GRAY);
- tv.setTypeface(CONDENSED);
- tv.setAllCaps(true);
- tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, tv.getTextSize() * 1.2f);
- final int p = (int) tv.getTextSize() / 2;
- if (inDropdown) {
- tv.setPadding(p, p, 0, p);
- } else {
- tv.setGravity(Gravity.CENTER_HORIZONTAL);
- tv.setPadding(p, 0, 0, 0);
- }
- }
- tv.setOnTouchListener(new OnTouchListener(){
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (DEBUG) log("onTouch %s %s inDropdown=%s", tv.getText(),
- MotionEvent.actionToString(event.getAction()), inDropdown);
- if (inDropdown && mAdapter != null) {
- mAdapter.setMode(mode);
- }
- return false;
- }
- });
- return tv;
- }
- };
- adapter.add(Adapter.MODE_LIMITED);
- adapter.add(Adapter.MODE_FULL);
- setAdapter(adapter);
- }
-
- public void updateState() {
- int mode = mAdapter != null ? mAdapter.getMode() : Adapter.MODE_LIMITED;
- if (mode == Adapter.MODE_OFF) {
- mode = Adapter.MODE_LIMITED;
- }
- if (DEBUG) log("setSelectedMode " + mode);
- for (int i = 0; i < getAdapter().getCount(); i++) {
- if (getAdapter().getItem(i).equals(mode)) {
- if (DEBUG) log(" setting selection = " + i);
- setSelection(i, true);
- onDetachedFromWindow();
- }
- }
- }
- }
-
- private final class AlarmWarning extends LinearLayout {
- public AlarmWarning(Context context) {
- super(context);
- setOrientation(HORIZONTAL);
-
- final TextView tv = new TextView(mContext);
- tv.setTextColor(GRAY);
- tv.setGravity(Gravity.TOP);
- tv.setTypeface(CONDENSED);
- tv.setText(FULL_TEXT);
- addView(tv);
-
- final ImageView icon = new ImageView(mContext);
- icon.setAlpha(.75f);
- int size = (int)tv.getTextSize();
- icon.setImageResource(android.R.drawable.ic_dialog_alert);
- LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(size, size);
- final int p = size / 4;
- lp.bottomMargin = lp.topMargin = lp.rightMargin = lp.leftMargin = p;
- addView(icon, 0, lp);
- setPadding(p, 0, p, p);
- }
-
- public void updateState(boolean animate) {
- final float alpha = isFull() ? 1 : 0;
- if (alpha == getAlpha()) {
- return;
- }
- if (animate) {
- animate().alpha(alpha).start();
- } else {
- setAlpha(alpha);
- requestLayout();
- }
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java
index d2067a4..c97ba8d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java
@@ -39,8 +39,7 @@
private Callbacks mCallbacks;
private int mExitIndex;
- private int mMode;
- private int mCommittedMode;
+ private boolean mMode;
public ZenModeViewAdapter(Context context) {
mContext = context;
@@ -51,27 +50,15 @@
}
@Override
- public int getMode() {
+ public boolean getMode() {
return mMode;
}
@Override
- public void setMode(int mode) {
+ public void setMode(boolean mode) {
if (mode == mMode) return;
mMode = mode;
- dispatchChanged();
- }
-
- @Override
- public int getCommittedMode() {
- return mCommittedMode;
- }
-
- @Override
- public void setCommittedMode(int mode) {
- final int v = mode == MODE_LIMITED ? Settings.Global.ZEN_MODE_LIMITED
- : mode == MODE_FULL ? Settings.Global.ZEN_MODE_FULL
- : Settings.Global.ZEN_MODE_OFF;
+ final int v = mMode ? Settings.Global.ZEN_MODE_ON : Settings.Global.ZEN_MODE_OFF;
AsyncTask.execute(new Runnable() {
@Override
public void run() {
@@ -79,6 +66,7 @@
Settings.Global.ZEN_MODE, v);
}
});
+ dispatchChanged();
}
@Override
@@ -87,11 +75,6 @@
mExitIndex = 0;
dispatchChanged();
}
- final int mode = mCommittedMode == MODE_FULL ? MODE_FULL : MODE_LIMITED;
- if (mode != mMode) {
- mMode = mode;
- dispatchChanged();
- }
}
private void dispatchChanged() {
@@ -122,6 +105,11 @@
}
@Override
+ public int getExitConditionIndex() {
+ return mExitIndex;
+ }
+
+ @Override
public void select(ExitCondition ec) {
final int i = mExits.indexOf(ec);
if (i == -1 || i == mExitIndex) {
@@ -171,15 +159,13 @@
}
private void loadSettings() {
- mCommittedMode = getModeFromSetting();
+ mMode = getModeFromSetting();
}
- private int getModeFromSetting() {
+ private boolean getModeFromSetting() {
final int v = Settings.Global.getInt(mResolver,
Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
- if (v == Settings.Global.ZEN_MODE_LIMITED) return MODE_LIMITED;
- if (v == Settings.Global.ZEN_MODE_FULL) return MODE_FULL;
- return MODE_OFF;
+ return v != Settings.Global.ZEN_MODE_OFF;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ScrollAdapter.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ScrollAdapter.java
new file mode 100644
index 0000000..f35e22d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ScrollAdapter.java
@@ -0,0 +1,40 @@
+/*
+ * 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.statusbar.policy;
+
+import android.view.View;
+
+/**
+ * A scroll adapter which can be queried for meta information about the scroll state
+ */
+public interface ScrollAdapter {
+
+ /**
+ * @return Whether the view returned by {@link #getHostView()} is scrolled to the top
+ */
+ public boolean isScrolledToTop();
+
+ /**
+ * @return Whether the view returned by {@link #getHostView()} is scrolled to the bottom
+ */
+ public boolean isScrolledToBottom();
+
+ /**
+ * @return The view in which the scrolling is performed
+ */
+ public View getHostView();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
new file mode 100644
index 0000000..04b7f53
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -0,0 +1,862 @@
+/*
+ * 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.statusbar.stack;
+
+import android.content.Context;
+import android.content.res.Configuration;
+
+import android.graphics.Canvas;
+import android.graphics.Outline;
+import android.graphics.Paint;
+
+import android.util.AttributeSet;
+import android.util.Log;
+
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.widget.OverScroller;
+
+import com.android.systemui.ExpandHelper;
+import com.android.systemui.R;
+import com.android.systemui.SwipeHelper;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.stack.StackScrollState.ViewState;
+import com.android.systemui.statusbar.policy.ScrollAdapter;
+
+/**
+ * A layout which handles a dynamic amount of notifications and presents them in a scrollable stack.
+ */
+public class NotificationStackScrollLayout extends ViewGroup
+ implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter {
+
+ private static final String TAG = "NotificationStackScrollLayout";
+ private static final boolean DEBUG = false;
+
+ /**
+ * Sentinel value for no current active pointer. Used by {@link #mActivePointerId}.
+ */
+ private static final int INVALID_POINTER = -1;
+
+ private SwipeHelper mSwipeHelper;
+ private boolean mSwipingInProgress = true;
+ private int mCurrentStackHeight = Integer.MAX_VALUE;
+ private int mOwnScrollY;
+ private int mMaxLayoutHeight;
+
+ private VelocityTracker mVelocityTracker;
+ private OverScroller mScroller;
+ private int mTouchSlop;
+ private int mMinimumVelocity;
+ private int mMaximumVelocity;
+ private int mOverscrollDistance;
+ private int mOverflingDistance;
+ private boolean mIsBeingDragged;
+ private int mLastMotionY;
+ private int mActivePointerId;
+
+ private int mSidePaddings;
+ private Paint mDebugPaint;
+ private int mBackgroundRoundedRectCornerRadius;
+ private int mContentHeight;
+ private int mCollapsedSize;
+ private int mBottomStackPeekSize;
+ private int mEmptyMarginBottom;
+ private int mPaddingBetweenElements;
+
+ /**
+ * The algorithm which calculates the properties for our children
+ */
+ private StackScrollAlgorithm mStackScrollAlgorithm;
+
+ /**
+ * The current State this Layout is in
+ */
+ private final StackScrollState mCurrentStackScrollState = new StackScrollState(this);
+
+ private OnChildLocationsChangedListener mListener;
+
+ public NotificationStackScrollLayout(Context context) {
+ this(context, null);
+ }
+
+ public NotificationStackScrollLayout(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public NotificationStackScrollLayout(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public NotificationStackScrollLayout(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ initView(context);
+ if (DEBUG) {
+ setWillNotDraw(false);
+ mDebugPaint = new Paint();
+ mDebugPaint.setColor(0xffff0000);
+ mDebugPaint.setStrokeWidth(2);
+ mDebugPaint.setStyle(Paint.Style.STROKE);
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (DEBUG) {
+ int y = mCollapsedSize;
+ canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
+ y = (int) (getLayoutHeight() - mBottomStackPeekSize - mCollapsedSize);
+ canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
+ y = (int) getLayoutHeight();
+ canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
+ }
+ }
+
+ private void initView(Context context) {
+ mScroller = new OverScroller(getContext());
+ setFocusable(true);
+ setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
+ final ViewConfiguration configuration = ViewConfiguration.get(context);
+ mTouchSlop = configuration.getScaledTouchSlop();
+ mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
+ mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
+ mOverscrollDistance = configuration.getScaledOverscrollDistance();
+ mOverflingDistance = configuration.getScaledOverflingDistance();
+ float densityScale = getResources().getDisplayMetrics().density;
+ float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
+ mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop);
+
+ mSidePaddings = context.getResources()
+ .getDimensionPixelSize(R.dimen.notification_side_padding);
+ mBackgroundRoundedRectCornerRadius = context.getResources()
+ .getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_quantum_rounded_rect_radius);
+ mCollapsedSize = context.getResources()
+ .getDimensionPixelSize(R.dimen.notification_row_min_height);
+ mBottomStackPeekSize = context.getResources()
+ .getDimensionPixelSize(R.dimen.bottom_stack_peek_amount);
+ mEmptyMarginBottom = context.getResources().getDimensionPixelSize(
+ R.dimen.notification_stack_margin_bottom);
+ // currently the padding is in the elements themself
+ mPaddingBetweenElements = 0;
+ mStackScrollAlgorithm = new StackScrollAlgorithm(context);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int mode = MeasureSpec.getMode(widthMeasureSpec);
+ int size = MeasureSpec.getSize(widthMeasureSpec);
+ int childMeasureSpec = MeasureSpec.makeMeasureSpec(size - 2 * mSidePaddings, mode);
+ measureChildren(childMeasureSpec, heightMeasureSpec);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+
+ // we layout all our children centered on the top
+ float centerX = getWidth() / 2.0f;
+ for (int i = 0; i < getChildCount(); i++) {
+ View child = getChildAt(i);
+ float width = child.getMeasuredWidth();
+ float height = child.getMeasuredHeight();
+ int oldWidth = child.getWidth();
+ int oldHeight = child.getHeight();
+ child.layout((int) (centerX - width / 2.0f),
+ 0,
+ (int) (centerX + width / 2.0f),
+ (int) height);
+ updateChildOutline(child, width, height, oldWidth, oldHeight);
+ }
+ setMaxLayoutHeight(getHeight() - mEmptyMarginBottom);
+ updateScrollPositionIfNecessary();
+ updateChildren();
+ updateContentHeight();
+ }
+
+ public void setChildLocationsChangedListener(OnChildLocationsChangedListener listener) {
+ mListener = listener;
+ }
+
+ /**
+ * Returns the location the given child is currently rendered at.
+ *
+ * @param child the child to get the location for
+ * @return one of {@link ViewState}'s <code>LOCATION_*</code> constants
+ */
+ public int getChildLocation(View child) {
+ ViewState childViewState = mCurrentStackScrollState.getViewStateForView(child);
+ if (childViewState == null) {
+ return ViewState.LOCATION_UNKNOWN;
+ }
+ return childViewState.location;
+ }
+
+ private void setMaxLayoutHeight(int maxLayoutHeight) {
+ mMaxLayoutHeight = maxLayoutHeight;
+ updateAlgorithmHeight();
+ }
+
+ private void updateAlgorithmHeight() {
+ mStackScrollAlgorithm.setLayoutHeight(getLayoutHeight());
+ }
+
+ /**
+ * Updates the children views according to the stack scroll algorithm. Call this whenever
+ * modifications to {@link #mOwnScrollY} are performed to reflect it in the view layout.
+ */
+ private void updateChildren() {
+ if (!isCurrentlyAnimating()) {
+ mCurrentStackScrollState.setScrollY(mOwnScrollY);
+ mStackScrollAlgorithm.getStackScrollState(mCurrentStackScrollState);
+ mCurrentStackScrollState.apply();
+ mOwnScrollY = mCurrentStackScrollState.getScrollY();
+ if (mListener != null) {
+ mListener.onChildLocationsChanged(this);
+ }
+ } else {
+ // TODO: handle animation
+ }
+ }
+
+ private boolean isCurrentlyAnimating() {
+ return false;
+ }
+
+ private void updateChildOutline(View child,
+ float width,
+ float height,
+ int oldWidth,
+ int oldHeight) {
+ // The children currently have paddings inside themselfs because of the expansion
+ // visualization. In order for the shadows to work correctly we have to set the correct
+ // outline.
+ View container = child.findViewById(R.id.container);
+ if (container != null && (oldWidth != width || oldHeight != height)) {
+ Outline outline = getOutlineForSize(container.getLeft(),
+ container.getTop(),
+ container.getWidth(),
+ container.getHeight());
+ child.setOutline(outline);
+ }
+ }
+
+ private Outline getOutlineForSize(int leftInset, int topInset, int width, int height) {
+ Outline result = new Outline();
+ result.setRoundRect(leftInset, topInset, leftInset + width, topInset + height,
+ mBackgroundRoundedRectCornerRadius);
+ return result;
+ }
+
+ private void updateScrollPositionIfNecessary() {
+ int scrollRange = getScrollRange();
+ if (scrollRange < mOwnScrollY) {
+ mOwnScrollY = scrollRange;
+ }
+ }
+
+ public void setCurrentStackHeight(int currentStackHeight) {
+ this.mCurrentStackHeight = currentStackHeight;
+ updateAlgorithmHeight();
+ updateChildren();
+ }
+
+ /**
+ * Get the current height of the view. This is at most the msize of the view given by a the
+ * layout but it can also be made smaller by setting {@link #mCurrentStackHeight}
+ *
+ * @return either the layout height or the externally defined height, whichever is smaller
+ */
+ private float getLayoutHeight() {
+ return Math.min(mMaxLayoutHeight, mCurrentStackHeight);
+ }
+
+ public int getItemHeight() {
+ return mCollapsedSize;
+ }
+
+ public int getBottomStackPeekSize() {
+ return mBottomStackPeekSize;
+ }
+
+ public void setLongPressListener(View.OnLongClickListener listener) {
+ mSwipeHelper.setLongPressListener(listener);
+ }
+
+ public void onChildDismissed(View v) {
+ if (DEBUG) Log.v(TAG, "onChildDismissed: " + v);
+ final View veto = v.findViewById(R.id.veto);
+ if (veto != null && veto.getVisibility() != View.GONE) {
+ veto.performClick();
+ }
+ setSwipingInProgress(false);
+ }
+
+ public void onBeginDrag(View v) {
+ setSwipingInProgress(true);
+ }
+
+ public void onDragCancelled(View v) {
+ setSwipingInProgress(false);
+ }
+
+ public View getChildAtPosition(MotionEvent ev) {
+ return getChildAtPosition(ev.getX(), ev.getY());
+ }
+
+ public View getChildAtRawPosition(float touchX, float touchY) {
+ int[] location = new int[2];
+ getLocationOnScreen(location);
+ return getChildAtPosition(touchX - location[0],touchY - location[1]);
+ }
+
+ public View getChildAtPosition(float touchX, float touchY) {
+ // find the view under the pointer, accounting for GONE views
+ final int count = getChildCount();
+ for (int childIdx = 0; childIdx < count; childIdx++) {
+ View slidingChild = getChildAt(childIdx);
+ if (slidingChild.getVisibility() == GONE) {
+ continue;
+ }
+ float top = slidingChild.getTranslationY();
+ float bottom = top + slidingChild.getMeasuredHeight();
+ int left = slidingChild.getLeft();
+ int right = slidingChild.getRight();
+
+ if (touchY >= top && touchY <= bottom && touchX >= left && touchX <= right) {
+ return slidingChild;
+ }
+ }
+ return null;
+ }
+
+ public boolean canChildBeExpanded(View v) {
+ return v instanceof ExpandableNotificationRow
+ && ((ExpandableNotificationRow) v).isExpandable();
+ }
+
+ public void setUserExpandedChild(View v, boolean userExpanded) {
+ if (v instanceof ExpandableNotificationRow) {
+ ((ExpandableNotificationRow) v).setUserExpanded(userExpanded);
+ }
+ }
+
+ public void setUserLockedChild(View v, boolean userLocked) {
+ if (v instanceof ExpandableNotificationRow) {
+ ((ExpandableNotificationRow) v).setUserLocked(userLocked);
+ }
+ }
+
+ public View getChildContentView(View v) {
+ return v;
+ }
+
+ public boolean canChildBeDismissed(View v) {
+ final View veto = v.findViewById(R.id.veto);
+ return (veto != null && veto.getVisibility() != View.GONE);
+ }
+
+ private void setSwipingInProgress(boolean isSwiped) {
+ mSwipingInProgress = isSwiped;
+ if(isSwiped) {
+ requestDisallowInterceptTouchEvent(true);
+ }
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ float densityScale = getResources().getDisplayMetrics().density;
+ mSwipeHelper.setDensityScale(densityScale);
+ float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
+ mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
+ initView(getContext());
+ }
+
+ public void dismissRowAnimated(View child, int vel) {
+ mSwipeHelper.dismissChild(child, vel);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ boolean scrollerWantsIt = false;
+ if (!mSwipingInProgress) {
+ scrollerWantsIt = onScrollTouch(ev);
+ }
+ boolean horizontalSwipeWantsIt = false;
+ if (!mIsBeingDragged) {
+ horizontalSwipeWantsIt = mSwipeHelper.onTouchEvent(ev);
+ }
+ return horizontalSwipeWantsIt || scrollerWantsIt || super.onTouchEvent(ev);
+ }
+
+ private boolean onScrollTouch(MotionEvent ev) {
+ initVelocityTrackerIfNotExists();
+ mVelocityTracker.addMovement(ev);
+
+ final int action = ev.getAction();
+
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN: {
+ if (getChildCount() == 0) {
+ return false;
+ }
+ boolean isBeingDragged = !mScroller.isFinished();
+ setIsBeingDragged(isBeingDragged);
+
+ /*
+ * If being flinged and user touches, stop the fling. isFinished
+ * will be false if being flinged.
+ */
+ if (!mScroller.isFinished()) {
+ mScroller.abortAnimation();
+ }
+
+ // Remember where the motion event started
+ mLastMotionY = (int) ev.getY();
+ mActivePointerId = ev.getPointerId(0);
+ break;
+ }
+ case MotionEvent.ACTION_MOVE:
+ final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
+ if (activePointerIndex == -1) {
+ Log.e(TAG, "Invalid pointerId=" + mActivePointerId + " in onTouchEvent");
+ break;
+ }
+
+ final int y = (int) ev.getY(activePointerIndex);
+ int deltaY = mLastMotionY - y;
+ if (!mIsBeingDragged && Math.abs(deltaY) > mTouchSlop) {
+ setIsBeingDragged(true);
+ if (deltaY > 0) {
+ deltaY -= mTouchSlop;
+ } else {
+ deltaY += mTouchSlop;
+ }
+ }
+ if (mIsBeingDragged) {
+ // Scroll to follow the motion event
+ mLastMotionY = y;
+
+ final int oldX = mScrollX;
+ final int oldY = mOwnScrollY;
+ final int range = getScrollRange();
+ final int overscrollMode = getOverScrollMode();
+ final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS ||
+ (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0);
+
+ // Calling overScrollBy will call onOverScrolled, which
+ // calls onScrollChanged if applicable.
+ if (overScrollBy(0, deltaY, 0, mOwnScrollY,
+ 0, range, 0, mOverscrollDistance, true)) {
+ // Break our velocity if we hit a scroll barrier.
+ mVelocityTracker.clear();
+ }
+ // TODO: Overscroll
+// if (canOverscroll) {
+// final int pulledToY = oldY + deltaY;
+// if (pulledToY < 0) {
+// mEdgeGlowTop.onPull((float) deltaY / getHeight());
+// if (!mEdgeGlowBottom.isFinished()) {
+// mEdgeGlowBottom.onRelease();
+// }
+// } else if (pulledToY > range) {
+// mEdgeGlowBottom.onPull((float) deltaY / getHeight());
+// if (!mEdgeGlowTop.isFinished()) {
+// mEdgeGlowTop.onRelease();
+// }
+// }
+// if (mEdgeGlowTop != null
+// && (!mEdgeGlowTop.isFinished() || !mEdgeGlowBottom.isFinished())){
+// postInvalidateOnAnimation();
+// }
+// }
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ if (mIsBeingDragged) {
+ final VelocityTracker velocityTracker = mVelocityTracker;
+ velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+ int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
+
+ if (getChildCount() > 0) {
+ if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
+ fling(-initialVelocity);
+ } else {
+ if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0,
+ getScrollRange())) {
+ postInvalidateOnAnimation();
+ }
+ }
+ }
+
+ mActivePointerId = INVALID_POINTER;
+ endDrag();
+ }
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ if (mIsBeingDragged && getChildCount() > 0) {
+ if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange())) {
+ postInvalidateOnAnimation();
+ }
+ mActivePointerId = INVALID_POINTER;
+ endDrag();
+ }
+ break;
+ case MotionEvent.ACTION_POINTER_DOWN: {
+ final int index = ev.getActionIndex();
+ mLastMotionY = (int) ev.getY(index);
+ mActivePointerId = ev.getPointerId(index);
+ break;
+ }
+ case MotionEvent.ACTION_POINTER_UP:
+ onSecondaryPointerUp(ev);
+ mLastMotionY = (int) ev.getY(ev.findPointerIndex(mActivePointerId));
+ break;
+ }
+ return true;
+ }
+
+ private void onSecondaryPointerUp(MotionEvent ev) {
+ final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
+ MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ final int pointerId = ev.getPointerId(pointerIndex);
+ if (pointerId == mActivePointerId) {
+ // This was our active pointer going up. Choose a new
+ // active pointer and adjust accordingly.
+ // TODO: Make this decision more intelligent.
+ final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
+ mLastMotionY = (int) ev.getY(newPointerIndex);
+ mActivePointerId = ev.getPointerId(newPointerIndex);
+ if (mVelocityTracker != null) {
+ mVelocityTracker.clear();
+ }
+ }
+ }
+
+ private void initVelocityTrackerIfNotExists() {
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ }
+
+ private void recycleVelocityTracker() {
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+ }
+
+ private void initOrResetVelocityTracker() {
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ } else {
+ mVelocityTracker.clear();
+ }
+ }
+
+ @Override
+ public void computeScroll() {
+ if (mScroller.computeScrollOffset()) {
+ // This is called at drawing time by ViewGroup.
+ int oldX = mScrollX;
+ int oldY = mOwnScrollY;
+ int x = mScroller.getCurrX();
+ int y = mScroller.getCurrY();
+
+ if (oldX != x || oldY != y) {
+ final int range = getScrollRange();
+ final int overscrollMode = getOverScrollMode();
+ final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS ||
+ (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0);
+
+ overScrollBy(x - oldX, y - oldY, oldX, oldY, 0, range,
+ 0, mOverflingDistance, false);
+ onScrollChanged(mScrollX, mOwnScrollY, oldX, oldY);
+
+ if (canOverscroll) {
+ // TODO: Overscroll
+// if (y < 0 && oldY >= 0) {
+// mEdgeGlowTop.onAbsorb((int) mScroller.getCurrVelocity());
+// } else if (y > range && oldY <= range) {
+// mEdgeGlowBottom.onAbsorb((int) mScroller.getCurrVelocity());
+// }
+ }
+ updateChildren();
+ }
+
+ // Keep on drawing until the animation has finished.
+ postInvalidateOnAnimation();
+ }
+ }
+
+ public void customScrollBy(int y) {
+ mOwnScrollY += y;
+ updateChildren();
+ }
+
+ public void customScrollTo(int y) {
+ mOwnScrollY = y;
+ updateChildren();
+ }
+
+ @Override
+ protected void onOverScrolled(int scrollX, int scrollY,
+ boolean clampedX, boolean clampedY) {
+ // Treat animating scrolls differently; see #computeScroll() for why.
+ if (!mScroller.isFinished()) {
+ final int oldX = mScrollX;
+ final int oldY = mOwnScrollY;
+ mScrollX = scrollX;
+ mOwnScrollY = scrollY;
+ invalidateParentIfNeeded();
+ onScrollChanged(mScrollX, mOwnScrollY, oldX, oldY);
+ if (clampedY) {
+ mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange());
+ }
+ updateChildren();
+ } else {
+ customScrollTo(scrollY);
+ scrollTo(scrollX, mScrollY);
+ }
+ }
+
+ private int getScrollRange() {
+ int scrollRange = 0;
+ if (getChildCount() > 0) {
+ int contentHeight = getContentHeight();
+ scrollRange = Math.max(0,
+ contentHeight - mMaxLayoutHeight + mBottomStackPeekSize);
+ }
+ return scrollRange;
+ }
+
+ private int getContentHeight() {
+ return mContentHeight;
+ }
+
+ private void updateContentHeight() {
+ int height = 0;
+ for (int i = 0; i < getChildCount(); i++) {
+ View child = getChildAt(i);
+ height += child.getHeight();
+ if (i < getChildCount()-1) {
+ height += mPaddingBetweenElements;
+ }
+ }
+ mContentHeight = height;
+ }
+
+ /**
+ * Fling the scroll view
+ *
+ * @param velocityY The initial velocity in the Y direction. Positive
+ * numbers mean that the finger/cursor is moving down the screen,
+ * which means we want to scroll towards the top.
+ */
+ private void fling(int velocityY) {
+ if (getChildCount() > 0) {
+ int height = (int) getLayoutHeight();
+ int bottom = getContentHeight();
+
+ mScroller.fling(mScrollX, mOwnScrollY, 0, velocityY, 0, 0, 0,
+ Math.max(0, bottom - height), 0, height/2);
+
+ postInvalidateOnAnimation();
+ }
+ }
+
+ private void endDrag() {
+ setIsBeingDragged(false);
+
+ recycleVelocityTracker();
+
+ // TODO: Overscroll
+// if (mEdgeGlowTop != null) {
+// mEdgeGlowTop.onRelease();
+// mEdgeGlowBottom.onRelease();
+// }
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ boolean scrollWantsIt = false;
+ if (!mSwipingInProgress) {
+ scrollWantsIt = onInterceptTouchEventScroll(ev);
+ }
+ boolean swipeWantsIt = false;
+ if (!mIsBeingDragged) {
+ swipeWantsIt = mSwipeHelper.onInterceptTouchEvent(ev);
+ }
+ return swipeWantsIt || scrollWantsIt ||
+ super.onInterceptTouchEvent(ev);
+ }
+
+ private boolean onInterceptTouchEventScroll(MotionEvent ev) {
+ /*
+ * This method JUST determines whether we want to intercept the motion.
+ * If we return true, onMotionEvent will be called and we do the actual
+ * scrolling there.
+ */
+
+ /*
+ * Shortcut the most recurring case: the user is in the dragging
+ * state and he is moving his finger. We want to intercept this
+ * motion.
+ */
+ final int action = ev.getAction();
+ if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) {
+ return true;
+ }
+
+ /*
+ * Don't try to intercept touch if we can't scroll anyway.
+ */
+ if (mOwnScrollY == 0 && getScrollRange() == 0) {
+ return false;
+ }
+
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_MOVE: {
+ /*
+ * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
+ * whether the user has moved far enough from his original down touch.
+ */
+
+ /*
+ * Locally do absolute value. mLastMotionY is set to the y value
+ * of the down event.
+ */
+ final int activePointerId = mActivePointerId;
+ if (activePointerId == INVALID_POINTER) {
+ // If we don't have a valid id, the touch down wasn't on content.
+ break;
+ }
+
+ final int pointerIndex = ev.findPointerIndex(activePointerId);
+ if (pointerIndex == -1) {
+ Log.e(TAG, "Invalid pointerId=" + activePointerId
+ + " in onInterceptTouchEvent");
+ break;
+ }
+
+ final int y = (int) ev.getY(pointerIndex);
+ final int yDiff = Math.abs(y - mLastMotionY);
+ if (yDiff > mTouchSlop) {
+ setIsBeingDragged(true);
+ mLastMotionY = y;
+ initVelocityTrackerIfNotExists();
+ mVelocityTracker.addMovement(ev);
+ }
+ break;
+ }
+
+ case MotionEvent.ACTION_DOWN: {
+ final int y = (int) ev.getY();
+ if (getChildAtPosition(ev.getX(), y) == null) {
+ setIsBeingDragged(false);
+ recycleVelocityTracker();
+ break;
+ }
+
+ /*
+ * Remember location of down touch.
+ * ACTION_DOWN always refers to pointer index 0.
+ */
+ mLastMotionY = y;
+ mActivePointerId = ev.getPointerId(0);
+
+ initOrResetVelocityTracker();
+ mVelocityTracker.addMovement(ev);
+ /*
+ * If being flinged and user touches the screen, initiate drag;
+ * otherwise don't. mScroller.isFinished should be false when
+ * being flinged.
+ */
+ boolean isBeingDragged = !mScroller.isFinished();
+ setIsBeingDragged(isBeingDragged);
+ break;
+ }
+
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ /* Release the drag */
+ setIsBeingDragged(false);
+ mActivePointerId = INVALID_POINTER;
+ recycleVelocityTracker();
+ if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange())) {
+ postInvalidateOnAnimation();
+ }
+ break;
+ case MotionEvent.ACTION_POINTER_UP:
+ onSecondaryPointerUp(ev);
+ break;
+ }
+
+ /*
+ * The only time we want to intercept motion events is if we are in the
+ * drag mode.
+ */
+ return mIsBeingDragged;
+ }
+
+ private void setIsBeingDragged(boolean isDragged) {
+ mIsBeingDragged = isDragged;
+ if (isDragged) {
+ requestDisallowInterceptTouchEvent(true);
+ mSwipeHelper.removeLongPressCallback();
+ }
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ super.onWindowFocusChanged(hasWindowFocus);
+ if (!hasWindowFocus) {
+ mSwipeHelper.removeLongPressCallback();
+ }
+ }
+
+ @Override
+ public boolean isScrolledToTop() {
+ return mOwnScrollY == 0;
+ }
+
+ @Override
+ public boolean isScrolledToBottom() {
+ return mOwnScrollY >= getScrollRange();
+ }
+
+ @Override
+ public View getHostView() {
+ return this;
+ }
+
+ public int getEmptyBottomMargin() {
+ return Math.max(getHeight() - mContentHeight, 0);
+ }
+
+ /**
+ * A listener that is notified when some child locations might have changed.
+ */
+ public interface OnChildLocationsChangedListener {
+ public void onChildLocationsChanged(NotificationStackScrollLayout stackScrollLayout);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/PiecewiseLinearIndentationFunctor.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/PiecewiseLinearIndentationFunctor.java
new file mode 100644
index 0000000..38b544f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/PiecewiseLinearIndentationFunctor.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.statusbar.stack;
+
+import java.util.ArrayList;
+
+/**
+ * A Functor which interpolates the stack distance linearly based on base values.
+ * The base values are based on an interpolation between a linear function and a
+ * quadratic function
+ */
+public class PiecewiseLinearIndentationFunctor extends StackIndentationFunctor {
+
+ private final ArrayList<Float> mBaseValues;
+ private final float mLinearPart;
+
+ /**
+ * @param maxItemsInStack The maximum number of items which should be visible at the same time,
+ * i.e the function returns totalTransitionDistance for the element with
+ * index maxItemsInStack
+ * @param peekSize The visual appearance of this is how far the cards in the stack peek
+ * out below the top card and it is measured in real pixels.
+ * Note that the visual appearance does not necessarily always correspond to
+ * the actual visual distance below the top card but is a maximum,
+ * achieved when the next card just starts transitioning into the stack and
+ * the stack is full.
+ * If totalTransitionDistance is equal to this, we directly start at the peek,
+ * otherwise the first element transitions between 0 and
+ * totalTransitionDistance - peekSize.
+ * Visualization:
+ * --------------------------------------------------- ---
+ * | | |
+ * | FIRST ITEM | | <- totalTransitionDistance
+ * | | |
+ * |---------------------------------------------------| | ---
+ * |__________________SECOND ITEM______________________| | | <- peekSize
+ * |===================================================| _|_ _|_
+ *
+ * @param totalTransitionDistance The total transition distance an element has to go through
+ * @param linearPart The interpolation factor between the linear and the quadratic amount taken.
+ * This factor must be somewhere in [0 , 1]
+ */
+ PiecewiseLinearIndentationFunctor(int maxItemsInStack,
+ int peekSize,
+ int totalTransitionDistance,
+ float linearPart) {
+ super(maxItemsInStack, peekSize, totalTransitionDistance);
+ mBaseValues = new ArrayList<Float>(maxItemsInStack+1);
+ initBaseValues();
+ mLinearPart = linearPart;
+ }
+
+ private void initBaseValues() {
+ int sumOfSquares = getSumOfSquares(mMaxItemsInStack-1);
+ int totalWeight = 0;
+ mBaseValues.add(0.0f);
+ for (int i = 0; i < mMaxItemsInStack - 1; i++) {
+ totalWeight += (mMaxItemsInStack - i - 1) * (mMaxItemsInStack - i - 1);
+ mBaseValues.add((float) totalWeight / sumOfSquares);
+ }
+ }
+
+ /**
+ * Get the sum of squares up to and including n, i.e sum(i * i, 1, n)
+ *
+ * @param n the maximum square to include
+ * @return
+ */
+ private int getSumOfSquares(int n) {
+ return n * (n + 1) * (2 * n + 1) / 6;
+ }
+
+ @Override
+ public float getValue(float itemsBefore) {
+ if (mStackStartsAtPeek) {
+ // We directly start at the stack, so no initial interpolation.
+ itemsBefore++;
+ }
+ if (itemsBefore < 0) {
+ return 0;
+ } else if (itemsBefore >= mMaxItemsInStack) {
+ return mTotalTransitionDistance;
+ }
+ int below = (int) itemsBefore;
+ float partialIn = itemsBefore - below;
+
+ if (below == 0) {
+ return mDistanceToPeekStart * partialIn;
+ } else {
+ float result = mDistanceToPeekStart;
+ float progress = mBaseValues.get(below - 1) * (1 - partialIn)
+ + mBaseValues.get(below) * partialIn;
+ result += (progress * (1 - mLinearPart)
+ + (itemsBefore - 1) / (mMaxItemsInStack - 1) * mLinearPart) * mPeekSize;
+ return result;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackIndentationFunctor.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackIndentationFunctor.java
new file mode 100644
index 0000000..f72947a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackIndentationFunctor.java
@@ -0,0 +1,74 @@
+/*
+ * 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.statusbar.stack;
+
+/**
+ * A functor which can be queried for offset given the number of items before it.
+ */
+public abstract class StackIndentationFunctor {
+
+ protected final int mTotalTransitionDistance;
+ protected final int mDistanceToPeekStart;
+ protected int mMaxItemsInStack;
+ protected int mPeekSize;
+ protected boolean mStackStartsAtPeek;
+
+ /**
+ * @param maxItemsInStack The maximum number of items which should be visible at the same time,
+ * i.e the function returns totalTransitionDistance for the element with
+ * index maxItemsInStack
+ * @param peekSize The visual appearance of this is how far the cards in the stack peek
+ * out below the top card and it is measured in real pixels.
+ * Note that the visual appearance does not necessarily always correspond to
+ * the actual visual distance below the top card but is a maximum,
+ * achieved when the next card just starts transitioning into the stack and
+ * the stack is full.
+ * If totalTransitionDistance is equal to this, we directly start at the peek,
+ * otherwise the first element transitions between 0 and
+ * totalTransitionDistance - peekSize.
+ * Visualization:
+ * --------------------------------------------------- ---
+ * | | |
+ * | FIRST ITEM | | <- totalTransitionDistance
+ * | | |
+ * |---------------------------------------------------| | ---
+ * |__________________SECOND ITEM______________________| | | <- peekSize
+ * |===================================================| _|_ _|_
+ *
+ * @param totalTransitionDistance The total transition distance an element has to go through
+ */
+ StackIndentationFunctor(int maxItemsInStack, int peekSize, int totalTransitionDistance) {
+ mTotalTransitionDistance = totalTransitionDistance;
+ mDistanceToPeekStart = mTotalTransitionDistance - peekSize;
+ mStackStartsAtPeek = mDistanceToPeekStart == 0;
+ mMaxItemsInStack = maxItemsInStack;
+ mPeekSize = peekSize;
+
+ }
+
+ public void setPeekSize(int mPeekSize) {
+ this.mPeekSize = mPeekSize;
+ }
+
+ /**
+ * Gets the offset of this Functor given a the quantity of items before it
+ *
+ * @param itemsBefore how many items are already in the stack before this element
+ * @return the offset
+ */
+ public abstract float getValue(float itemsBefore);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
new file mode 100644
index 0000000..4745f3b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -0,0 +1,420 @@
+/*
+ * 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.statusbar.stack;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import com.android.systemui.R;
+
+/**
+ * The Algorithm of the {@link com.android.systemui.statusbar.stack
+ * .NotificationStackScrollLayout} which can be queried for {@link com.android.systemui.statusbar
+ * .stack.StackScrollState}
+ */
+public class StackScrollAlgorithm {
+
+ private static final String LOG_TAG = "StackScrollAlgorithm";
+
+ private static final int MAX_ITEMS_IN_BOTTOM_STACK = 3;
+ private static final int MAX_ITEMS_IN_TOP_STACK = 3;
+
+ private int mPaddingBetweenElements;
+ private int mCollapsedSize;
+ private int mTopStackPeekSize;
+ private int mBottomStackPeekSize;
+ private int mZDistanceBetweenElements;
+ private int mZBasicHeight;
+
+ private StackIndentationFunctor mTopStackIndentationFunctor;
+ private StackIndentationFunctor mBottomStackIndentationFunctor;
+
+ private float mLayoutHeight;
+ private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
+
+ public StackScrollAlgorithm(Context context) {
+ initConstants(context);
+ }
+
+ private void initConstants(Context context) {
+
+ // currently the padding is in the elements themself
+ mPaddingBetweenElements = 0;
+ mCollapsedSize = context.getResources()
+ .getDimensionPixelSize(R.dimen.notification_row_min_height);
+ mTopStackPeekSize = context.getResources()
+ .getDimensionPixelSize(R.dimen.top_stack_peek_amount);
+ mBottomStackPeekSize = context.getResources()
+ .getDimensionPixelSize(R.dimen.bottom_stack_peek_amount);
+ mZDistanceBetweenElements = context.getResources()
+ .getDimensionPixelSize(R.dimen.z_distance_between_notifications);
+ mZBasicHeight = (MAX_ITEMS_IN_BOTTOM_STACK + 1) * mZDistanceBetweenElements;
+
+ mTopStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
+ MAX_ITEMS_IN_TOP_STACK,
+ mTopStackPeekSize,
+ mCollapsedSize + mPaddingBetweenElements,
+ 0.5f);
+ mBottomStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
+ MAX_ITEMS_IN_BOTTOM_STACK,
+ mBottomStackPeekSize,
+ mBottomStackPeekSize,
+ 0.5f);
+ }
+
+
+ public void getStackScrollState(StackScrollState resultState) {
+ // The state of the local variables are saved in an algorithmState to easily subdivide it
+ // into multiple phases.
+ StackScrollAlgorithmState algorithmState = mTempAlgorithmState;
+
+ // First we reset the view states to their default values.
+ resultState.resetViewStates();
+
+ // The first element is always in there so it's initialized with 1.0f;
+ algorithmState.itemsInTopStack = 1.0f;
+ algorithmState.partialInTop = 0.0f;
+ algorithmState.lastTopStackIndex = 0;
+ algorithmState.scrollY = resultState.getScrollY();
+ algorithmState.itemsInBottomStack = 0.0f;
+
+ // Phase 1:
+ findNumberOfItemsInTopStackAndUpdateState(resultState, algorithmState);
+
+ // Phase 2:
+ updatePositionsForState(resultState, algorithmState);
+
+ // Phase 3:
+ updateZValuesForState(resultState, algorithmState);
+
+ // write the algorithm state to the result
+ resultState.setScrollY(algorithmState.scrollY);
+ }
+
+ /**
+ * Determine the positions for the views. This is the main part of the algorithm.
+ *
+ * @param resultState The result state to update if a change to the properties of a child occurs
+ * @param algorithmState The state in which the current pass of the algorithm is currently in
+ * and which will be updated
+ */
+ private void updatePositionsForState(StackScrollState resultState,
+ StackScrollAlgorithmState algorithmState) {
+ float stackHeight = getLayoutHeight();
+
+ // The position where the bottom stack starts.
+ float transitioningPositionStart = stackHeight - mCollapsedSize - mBottomStackPeekSize;
+
+ // The y coordinate of the current child.
+ float currentYPosition = 0.0f;
+
+ // How far in is the element currently transitioning into the bottom stack.
+ float yPositionInScrollView = 0.0f;
+
+ ViewGroup hostView = resultState.getHostView();
+ int childCount = hostView.getChildCount();
+ int numberOfElementsCompletelyIn = (int) algorithmState.itemsInTopStack;
+ for (int i = 0; i < childCount; i++) {
+ View child = hostView.getChildAt(i);
+ StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
+ childViewState.yTranslation = currentYPosition;
+ childViewState.location = StackScrollState.ViewState.LOCATION_UNKNOWN;
+ int childHeight = child.getHeight();
+ // The y position after this element
+ float nextYPosition = currentYPosition + childHeight + mPaddingBetweenElements;
+ float yPositionInScrollViewAfterElement = yPositionInScrollView
+ + childHeight
+ + mPaddingBetweenElements;
+ float scrollOffset = yPositionInScrollViewAfterElement - algorithmState.scrollY;
+ if (i < algorithmState.lastTopStackIndex) {
+ // Case 1:
+ // We are in the top Stack
+ nextYPosition = updateStateForTopStackChild(algorithmState,
+ numberOfElementsCompletelyIn,
+ i, childViewState);
+ } else if (i == algorithmState.lastTopStackIndex) {
+ // Case 2:
+ // First element of regular scrollview comes next, so the position is just the
+ // scrolling position
+ nextYPosition = Math.min(scrollOffset, transitioningPositionStart);
+ childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_PEEKING;
+ } else if (nextYPosition >= transitioningPositionStart) {
+ if (currentYPosition >= transitioningPositionStart) {
+ // Case 3:
+ // According to the regular scroll view we are fully translated out of the
+ // bottom of the screen so we are fully in the bottom stack
+ nextYPosition = updateStateForChildFullyInBottomStack(algorithmState,
+ transitioningPositionStart, childViewState, childHeight);
+ } else {
+ // Case 4:
+ // According to the regular scroll view we are currently translating out of /
+ // into the bottom of the screen
+ nextYPosition = updateStateForChildTransitioningInBottom(
+ algorithmState, stackHeight, transitioningPositionStart,
+ currentYPosition, childViewState,
+ childHeight, nextYPosition);
+ }
+ } else {
+ childViewState.location = StackScrollState.ViewState.LOCATION_MAIN_AREA;
+ }
+ // The first card is always rendered.
+ if (i == 0) {
+ childViewState.alpha = 1.0f;
+ childViewState.location = StackScrollState.ViewState.LOCATION_FIRST_CARD;
+ }
+ if (childViewState.location == StackScrollState.ViewState.LOCATION_UNKNOWN) {
+ Log.wtf(LOG_TAG, "Failed to assign location for child " + i);
+ }
+ nextYPosition = Math.max(0, nextYPosition);
+ currentYPosition = nextYPosition;
+ yPositionInScrollView = yPositionInScrollViewAfterElement;
+ }
+ }
+
+ private float updateStateForChildTransitioningInBottom(StackScrollAlgorithmState algorithmState,
+ float stackHeight, float transitioningPositionStart, float currentYPosition,
+ StackScrollState.ViewState childViewState, int childHeight, float nextYPosition) {
+ float newSize = transitioningPositionStart + mCollapsedSize - currentYPosition;
+ newSize = Math.min(childHeight, newSize);
+ // Transitioning element on top of bottom stack:
+ algorithmState.partialInBottom = 1.0f - (
+ (stackHeight - mBottomStackPeekSize - nextYPosition) / mCollapsedSize);
+ // Our element can be expanded, so we might even have to scroll further than
+ // mCollapsedSize
+ algorithmState.partialInBottom = Math.min(1.0f, algorithmState.partialInBottom);
+ float offset = mBottomStackIndentationFunctor.getValue(
+ algorithmState.partialInBottom);
+ nextYPosition = transitioningPositionStart + offset;
+ algorithmState.itemsInBottomStack += algorithmState.partialInBottom;
+ // TODO: only temporarily collapse
+ if (childHeight != (int) newSize) {
+ childViewState.height = (int) newSize;
+ }
+ childViewState.location = StackScrollState.ViewState.LOCATION_MAIN_AREA;
+
+ return nextYPosition;
+ }
+
+ private float updateStateForChildFullyInBottomStack(StackScrollAlgorithmState algorithmState,
+ float transitioningPositionStart, StackScrollState.ViewState childViewState,
+ int childHeight) {
+
+ float nextYPosition;
+ algorithmState.itemsInBottomStack += 1.0f;
+ if (algorithmState.itemsInBottomStack < MAX_ITEMS_IN_BOTTOM_STACK) {
+ // We are visually entering the bottom stack
+ nextYPosition = transitioningPositionStart
+ + mBottomStackIndentationFunctor.getValue(
+ algorithmState.itemsInBottomStack);
+ childViewState.location = StackScrollState.ViewState.LOCATION_BOTTOM_STACK_PEEKING;
+ } else {
+ // we are fully inside the stack
+ if (algorithmState.itemsInBottomStack > MAX_ITEMS_IN_BOTTOM_STACK + 2) {
+ childViewState.alpha = 0.0f;
+ } else if (algorithmState.itemsInBottomStack
+ > MAX_ITEMS_IN_BOTTOM_STACK + 1) {
+ childViewState.alpha = 1.0f - algorithmState.partialInBottom;
+ }
+ childViewState.location = StackScrollState.ViewState.LOCATION_BOTTOM_STACK_HIDDEN;
+ nextYPosition = transitioningPositionStart + mBottomStackPeekSize;
+ }
+ // TODO: only temporarily collapse
+ if (childHeight != mCollapsedSize) {
+ childViewState.height = mCollapsedSize;
+ }
+ return nextYPosition;
+ }
+
+ private float updateStateForTopStackChild(StackScrollAlgorithmState algorithmState,
+ int numberOfElementsCompletelyIn, int i, StackScrollState.ViewState childViewState) {
+
+ float nextYPosition = 0;
+
+ // First we calculate the index relative to the current stack window of size at most
+ // {@link #MAX_ITEMS_IN_TOP_STACK}
+ int paddedIndex = i
+ - Math.max(numberOfElementsCompletelyIn - MAX_ITEMS_IN_TOP_STACK, 0);
+ if (paddedIndex >= 0) {
+ // We are currently visually entering the top stack
+ nextYPosition = mCollapsedSize + mPaddingBetweenElements -
+ mTopStackIndentationFunctor.getValue(
+ algorithmState.itemsInTopStack - i - 1);
+ nextYPosition = Math.min(nextYPosition, mLayoutHeight - mCollapsedSize
+ - mBottomStackPeekSize);
+ if (paddedIndex == 0) {
+ childViewState.alpha = 1.0f - algorithmState.partialInTop;
+ childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_HIDDEN;
+ } else {
+ childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_PEEKING;
+ }
+ } else {
+ // We are hidden behind the top card and faded out, so we can hide ourselves.
+ childViewState.alpha = 0.0f;
+ childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_HIDDEN;
+ }
+ return nextYPosition;
+ }
+
+ /**
+ * Find the number of items in the top stack and update the result state if needed.
+ *
+ * @param resultState The result state to update if a height change of an child occurs
+ * @param algorithmState The state in which the current pass of the algorithm is currently in
+ * and which will be updated
+ */
+ private void findNumberOfItemsInTopStackAndUpdateState(StackScrollState resultState,
+ StackScrollAlgorithmState algorithmState) {
+
+ // The y Position if the element would be in a regular scrollView
+ float yPositionInScrollView = 0.0f;
+ ViewGroup hostView = resultState.getHostView();
+ int childCount = hostView.getChildCount();
+
+ // find the number of elements in the top stack.
+ for (int i = 0; i < childCount; i++) {
+ View child = hostView.getChildAt(i);
+ StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
+ int childHeight = child.getHeight();
+ float yPositionInScrollViewAfterElement = yPositionInScrollView
+ + childHeight
+ + mPaddingBetweenElements;
+ if (yPositionInScrollView < algorithmState.scrollY) {
+ if (yPositionInScrollViewAfterElement <= algorithmState.scrollY) {
+ // According to the regular scroll view we are fully off screen
+ algorithmState.itemsInTopStack += 1.0f;
+ if (childHeight != mCollapsedSize) {
+ childViewState.height = mCollapsedSize;
+ }
+ } else {
+ // According to the regular scroll view we are partially off screen
+ // If it is expanded we have to collapse it to a new size
+ float newSize = yPositionInScrollViewAfterElement
+ - mPaddingBetweenElements
+ - algorithmState.scrollY;
+
+ // How much did we scroll into this child
+ algorithmState.partialInTop = (mCollapsedSize - newSize) / (mCollapsedSize
+ + mPaddingBetweenElements);
+
+ // Our element can be expanded, so this can get negative
+ algorithmState.partialInTop = Math.max(0.0f, algorithmState.partialInTop);
+ algorithmState.itemsInTopStack += algorithmState.partialInTop;
+ // TODO: handle overlapping sizes with end stack
+ newSize = Math.max(mCollapsedSize, newSize);
+ // TODO: only temporarily collapse
+ if (newSize != childHeight) {
+ childViewState.height = (int) newSize;
+
+ // We decrease scrollY by the same amount we made this child smaller.
+ // The new scroll position is therefore the start of the element
+ algorithmState.scrollY = (int) yPositionInScrollView;
+ resultState.setScrollY(algorithmState.scrollY);
+ }
+ if (childHeight > mCollapsedSize) {
+ // If we are just resizing this child, this element is not treated to be
+ // transitioning into the stack and therefore it is the last element in
+ // the stack.
+ algorithmState.lastTopStackIndex = i;
+ break;
+ }
+ }
+ } else {
+ algorithmState.lastTopStackIndex = i;
+
+ // We are already past the stack so we can end the loop
+ break;
+ }
+ yPositionInScrollView = yPositionInScrollViewAfterElement;
+ }
+ }
+
+ /**
+ * Calculate the Z positions for all children based on the number of items in both stacks and
+ * save it in the resultState
+ *
+ * @param resultState The result state to update the zTranslation values
+ * @param algorithmState The state in which the current pass of the algorithm is currently in
+ */
+ private void updateZValuesForState(StackScrollState resultState,
+ StackScrollAlgorithmState algorithmState) {
+ ViewGroup hostView = resultState.getHostView();
+ int childCount = hostView.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = hostView.getChildAt(i);
+ StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
+ if (i < algorithmState.itemsInTopStack) {
+ float stackIndex = algorithmState.itemsInTopStack - i;
+ stackIndex = Math.min(stackIndex, MAX_ITEMS_IN_TOP_STACK + 2);
+ childViewState.zTranslation = mZBasicHeight
+ + stackIndex * mZDistanceBetweenElements;
+ } else if (i > (childCount - 1 - algorithmState.itemsInBottomStack)) {
+ float numItemsAbove = i - (childCount - 1 - algorithmState.itemsInBottomStack);
+ float translationZ = mZBasicHeight
+ - numItemsAbove * mZDistanceBetweenElements;
+ childViewState.zTranslation = translationZ;
+ } else {
+ childViewState.zTranslation = mZBasicHeight;
+ }
+ }
+ }
+
+ public float getLayoutHeight() {
+ return mLayoutHeight;
+ }
+
+ public void setLayoutHeight(float layoutHeight) {
+ this.mLayoutHeight = layoutHeight;
+ }
+
+ class StackScrollAlgorithmState {
+
+ /**
+ * The scroll position of the algorithm
+ */
+ public int scrollY;
+
+ /**
+ * The quantity of items which are in the top stack.
+ */
+ public float itemsInTopStack;
+
+ /**
+ * how far in is the element currently transitioning into the top stack
+ */
+ public float partialInTop;
+
+ /**
+ * The last item index which is in the top stack.
+ * NOTE: In the top stack the item after the transitioning element is also in the stack!
+ * This is needed to ensure a smooth transition between the y position in the regular
+ * scrollview and the one in the stack.
+ */
+ public int lastTopStackIndex;
+
+ /**
+ * The quantity of items which are in the bottom stack.
+ */
+ public float itemsInBottomStack;
+
+ /**
+ * how far in is the element currently transitioning into the bottom stack
+ */
+ public float partialInBottom;
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
new file mode 100644
index 0000000..881730a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -0,0 +1,171 @@
+/*
+ * 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.statusbar.stack;
+
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A state of a {@link com.android.systemui.statusbar.stack.NotificationStackScrollLayout} which
+ * can be applied to a viewGroup.
+ */
+public class StackScrollState {
+
+ private static final String CHILD_NOT_FOUND_TAG = "StackScrollStateNoSuchChild";
+
+ private final ViewGroup mHostView;
+ private Map<View, ViewState> mStateMap;
+ private int mScrollY;
+
+ public int getScrollY() {
+ return mScrollY;
+ }
+
+ public void setScrollY(int scrollY) {
+ this.mScrollY = scrollY;
+ }
+
+ public StackScrollState(ViewGroup hostView) {
+ mHostView = hostView;
+ mStateMap = new HashMap<View, ViewState>();
+ }
+
+ public ViewGroup getHostView() {
+ return mHostView;
+ }
+
+ public void resetViewStates() {
+ int numChildren = mHostView.getChildCount();
+ for (int i = 0; i < numChildren; i++) {
+ View child = mHostView.getChildAt(i);
+ ViewState viewState = mStateMap.get(child);
+ if (viewState == null) {
+ viewState = new ViewState();
+ mStateMap.put(child, viewState);
+ }
+ // initialize with the default values of the view
+ viewState.height = child.getHeight();
+ viewState.alpha = 1.0f;
+ }
+ }
+
+
+ public ViewState getViewStateForView(View requestedView) {
+ return mStateMap.get(requestedView);
+ }
+
+ /**
+ * Apply the properties saved in {@link #mStateMap} to the children of the {@link #mHostView}.
+ * The properties are only applied if they effectively changed.
+ */
+ public void apply() {
+ int numChildren = mHostView.getChildCount();
+ for (int i = 0; i < numChildren; i++) {
+ View child = mHostView.getChildAt(i);
+ ViewState state = mStateMap.get(child);
+ if (state != null) {
+ float alpha = child.getAlpha();
+ float yTranslation = child.getTranslationY();
+ float zTranslation = child.getTranslationZ();
+ int height = child.getHeight();
+ float newAlpha = state.alpha;
+ float newYTranslation = state.yTranslation;
+ float newZTranslation = state.zTranslation;
+ int newHeight = state.height;
+ boolean becomesInvisible = newAlpha == 0.0f;
+ if (alpha != newAlpha) {
+ // apply layer type
+ boolean becomesFullyVisible = newAlpha == 1.0f;
+ boolean newLayerTypeIsHardware = !becomesInvisible && !becomesFullyVisible;
+ int layerType = child.getLayerType();
+ int newLayerType = newLayerTypeIsHardware
+ ? View.LAYER_TYPE_HARDWARE
+ : View.LAYER_TYPE_NONE;
+ if (layerType != newLayerType) {
+ child.setLayerType(newLayerType, null);
+ }
+
+ // apply alpha
+ if (!becomesInvisible) {
+ child.setAlpha(newAlpha);
+ }
+ }
+
+ // apply visibility
+ int oldVisibility = child.getVisibility();
+ int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
+ if (newVisibility != oldVisibility) {
+ child.setVisibility(newVisibility);
+ }
+
+ // apply yTranslation
+ if (yTranslation != newYTranslation) {
+ child.setTranslationY(newYTranslation);
+ }
+
+ // apply zTranslation
+ if (zTranslation != newZTranslation) {
+ child.setTranslationZ(newZTranslation);
+ }
+
+ // apply height
+ if (height != newHeight) {
+ applyNewHeight(child, newHeight);
+ }
+ } else {
+ Log.wtf(CHILD_NOT_FOUND_TAG, "No child state was found when applying this state " +
+ "to the hostView");
+ }
+ }
+ }
+
+ private void applyNewHeight(View child, int newHeight) {
+ ViewGroup.LayoutParams lp = child.getLayoutParams();
+ lp.height = newHeight;
+ child.setLayoutParams(lp);
+ }
+
+
+ public static class ViewState {
+
+ // These are flags such that we can create masks for filtering.
+
+ public static final int LOCATION_UNKNOWN = 0x00;
+ public static final int LOCATION_FIRST_CARD = 0x01;
+ public static final int LOCATION_TOP_STACK_HIDDEN = 0x02;
+ public static final int LOCATION_TOP_STACK_PEEKING = 0x04;
+ public static final int LOCATION_MAIN_AREA = 0x08;
+ public static final int LOCATION_BOTTOM_STACK_PEEKING = 0x10;
+ public static final int LOCATION_BOTTOM_STACK_HIDDEN = 0x20;
+
+ float alpha;
+ float yTranslation;
+ float zTranslation;
+ int height;
+
+ /**
+ * The location this view is currently rendered at.
+ *
+ * <p>See <code>LOCATION_</code> flags.</p>
+ */
+ int location;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 0adb32f..481266b 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -312,6 +312,7 @@
mUsbStorageNotification.setLatestEventInfo(mContext, title, message, pi);
mUsbStorageNotification.visibility = Notification.VISIBILITY_PUBLIC;
+ mUsbStorageNotification.category = Notification.CATEGORY_SYSTEM;
final boolean adbOn = 1 == Settings.Global.getInt(
mContext.getContentResolver(),
@@ -404,6 +405,7 @@
mMediaStorageNotification.icon = icon;
mMediaStorageNotification.setLatestEventInfo(mContext, title, message, pi);
mMediaStorageNotification.visibility = Notification.VISIBILITY_PUBLIC;
+ mMediaStorageNotification.category = Notification.CATEGORY_SYSTEM;
}
final int notificationId = mMediaStorageNotification.icon;
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index ef640d5..03d920a 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -1,10 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.vpndialogs">
<application android:label="VpnDialogs"
android:allowBackup="false" >
<activity android:name=".ConfirmDialog"
- android:theme="@*android:style/Theme.Holo.Dialog.Alert">
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
@@ -12,7 +30,7 @@
</activity>
<activity android:name=".ManageDialog"
- android:theme="@*android:style/Theme.Holo.Dialog.Alert"
+ android:theme="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
diff --git a/packages/WallpaperCropper/AndroidManifest.xml b/packages/WallpaperCropper/AndroidManifest.xml
index 27755bd..81d1085 100644
--- a/packages/WallpaperCropper/AndroidManifest.xml
+++ b/packages/WallpaperCropper/AndroidManifest.xml
@@ -1,3 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2014 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.wallpapercropper" >
<uses-permission android:name="android.permission.SET_WALLPAPER" />
diff --git a/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml b/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml
index 97d7001..cf78989 100644
--- a/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml
+++ b/packages/WallpaperCropper/res/layout/wallpaper_cropper.xml
@@ -28,7 +28,7 @@
android:layout_height="match_parent" />
<ProgressBar
android:id="@+id/loading"
- style="@android:style/Widget.Holo.ProgressBar.Large"
+ style="@android:style/Widget.DeviceDefault.Light.ProgressBar.Large"
android:visibility="invisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/packages/WallpaperCropper/res/values/styles.xml b/packages/WallpaperCropper/res/values/styles.xml
index 2b63fe0..b27a387 100644
--- a/packages/WallpaperCropper/res/values/styles.xml
+++ b/packages/WallpaperCropper/res/values/styles.xml
@@ -15,13 +15,13 @@
-->
<resources>
- <style name="Theme.WallpaperCropper" parent="@android:style/Theme.Holo">
+ <style name="Theme.WallpaperCropper" parent="@android:style/Theme.DeviceDefault.Light">
<item name="android:actionBarStyle">@style/WallpaperCropperActionBar</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowActionBarOverlay">true</item>
</style>
- <style name="WallpaperCropperActionBar" parent="android:style/Widget.Holo.ActionBar">
+ <style name="WallpaperCropperActionBar" parent="android:style/Widget.DeviceDefault.Light.ActionBar">
<item name="android:displayOptions">showCustom</item>
<item name="android:background">#88000000</item>
</style>
diff --git a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
index d6c0c99..5c8a8ef8 100644
--- a/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
+++ b/packages/WallpaperCropper/src/com/android/wallpapercropper/WallpaperCropActivity.java
@@ -363,16 +363,11 @@
// Get the crop
RectF cropRect = mCropView.getCrop();
- // Due to rounding errors in the cropview renderer the edges can be slightly offset
- // therefore we ensure that the boundaries are sanely defined
- cropRect.left = Math.max(0, cropRect.left);
- cropRect.right = Math.min(mCropView.getWidth(), cropRect.right);
- cropRect.top = Math.max(0, cropRect.top);
- cropRect.bottom = Math.min(mCropView.getHeight(), cropRect.bottom);
+ Point inSize = mCropView.getSourceDimensions();
+
int cropRotation = mCropView.getImageRotation();
float cropScale = mCropView.getWidth() / (float) cropRect.width();
- Point inSize = mCropView.getSourceDimensions();
Matrix rotateMatrix = new Matrix();
rotateMatrix.setRotate(cropRotation);
float[] rotatedInSize = new float[] { inSize.x, inSize.y };
@@ -380,6 +375,13 @@
rotatedInSize[0] = Math.abs(rotatedInSize[0]);
rotatedInSize[1] = Math.abs(rotatedInSize[1]);
+ // Due to rounding errors in the cropview renderer the edges can be slightly offset
+ // therefore we ensure that the boundaries are sanely defined
+ cropRect.left = Math.max(0, cropRect.left);
+ cropRect.right = Math.min(rotatedInSize[0], cropRect.right);
+ cropRect.top = Math.max(0, cropRect.top);
+ cropRect.bottom = Math.min(rotatedInSize[1], cropRect.bottom);
+
// ADJUST CROP WIDTH
// Extend the crop all the way to the right, for parallax
// (or all the way to the left, in RTL)
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 0120a03..6e025bb 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -121,13 +121,14 @@
filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
context.registerReceiver(mBroadcastReceiver, filter);
+ ConnectivityManager cm = (ConnectivityManager)
+ context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mHasTelephony = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
+
// get notified of phone state changes
TelephonyManager telephonyManager =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
- ConnectivityManager cm = (ConnectivityManager)
- context.getSystemService(Context.CONNECTIVITY_SERVICE);
- mHasTelephony = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
mContext.getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,
mAirplaneModeObserver);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index a65f677..f1db904 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -145,6 +145,7 @@
TypedValue mFixedWidthMinor;
TypedValue mFixedHeightMajor;
TypedValue mFixedHeightMinor;
+ TypedValue mOutsetBottom;
// This is the top-level view of the window, containing the window decor.
private DecorView mDecor;
@@ -2370,7 +2371,6 @@
} else {
h = 0;
}
-
if (h > 0) {
final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(
@@ -2379,6 +2379,15 @@
}
}
+ if (mOutsetBottom != null) {
+ int mode = MeasureSpec.getMode(heightMeasureSpec);
+ if (mode != MeasureSpec.UNSPECIFIED) {
+ int outset = (int) mOutsetBottom.getDimension(metrics);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(height + outset, mode);
+ }
+ }
+
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
@@ -2993,6 +3002,10 @@
if (a.getBoolean(com.android.internal.R.styleable.Window_windowContentTransitions, false)) {
requestFeature(FEATURE_CONTENT_TRANSITIONS);
}
+ if (a.hasValue(com.android.internal.R.styleable.Window_windowOutsetBottom)) {
+ if (mOutsetBottom == null) mOutsetBottom = new TypedValue();
+ a.getValue(com.android.internal.R.styleable.Window_windowOutsetBottom, mOutsetBottom);
+ }
final Context context = getContext();
final int targetSdk = context.getApplicationInfo().targetSdkVersion;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index ededbb2..ccdacea 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -3417,8 +3417,9 @@
}
final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
+ final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
if (appWindow) {
- if (showWhenLocked) {
+ if (showWhenLocked || (dismissKeyguard && !isKeyguardSecure())) {
mAppsToBeHidden.remove(win.getAppToken());
} else {
mAppsToBeHidden.add(win.getAppToken());
@@ -3435,8 +3436,7 @@
mHideLockScreen = true;
mForceStatusBarFromKeyguard = false;
}
- if ((fl & FLAG_DISMISS_KEYGUARD) != 0
- && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
+ if (dismissKeyguard && mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
if (DEBUG_LAYOUT) Slog.v(TAG,
"Setting mDismissKeyguard true by win " + win);
mDismissKeyguard = mWinDismissingKeyguard == win ?
diff --git a/rs/java/android/renderscript/RenderScriptGL.java b/rs/java/android/renderscript/RenderScriptGL.java
index 714e835..6178994 100644
--- a/rs/java/android/renderscript/RenderScriptGL.java
+++ b/rs/java/android/renderscript/RenderScriptGL.java
@@ -225,9 +225,13 @@
validate();
//android.util.Log.v("rs", "set surface " + sur + " w=" + w + ", h=" + h);
+ Surface s = null;
+ if (sur != null) {
+ s = new Surface(sur);
+ }
mWidth = w;
mHeight = h;
- nContextSetSurfaceTexture(w, h, sur);
+ nContextSetSurface(w, h, s);
}
/**
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 0edce11..35f873e 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -397,9 +397,8 @@
return true; // yes, recycle the event
}
if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) {
+ mSecurityPolicy.updateActiveWindowLocked(event.getWindowId(), event.getEventType());
mSecurityPolicy.updateEventSourceLocked(event);
- mMainHandler.obtainMessage(MainHandler.MSG_UPDATE_ACTIVE_WINDOW,
- event.getWindowId(), event.getEventType()).sendToTarget();
notifyAccessibilityServicesDelayedLocked(event, false);
notifyAccessibilityServicesDelayedLocked(event, true);
}
@@ -503,7 +502,7 @@
mGlobalWindowTokens.put(windowId, windowToken.asBinder());
if (DEBUG) {
Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid()
- + " with windowId: " + windowId);
+ + " with windowId: " + windowId + " and token: " + windowToken.asBinder());
}
} else {
AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper(
@@ -514,12 +513,10 @@
userState.mWindowTokens.put(windowId, windowToken.asBinder());
if (DEBUG) {
Slog.i(LOG_TAG, "Added user connection for pid:" + Binder.getCallingPid()
- + " with windowId: " + windowId + " and userId:" + mCurrentUserId);
+ + " with windowId: " + windowId + " and userId:" + mCurrentUserId
+ + " and token: " + windowToken.asBinder());
}
}
- if (DEBUG) {
- Slog.i(LOG_TAG, "Adding interaction connection to windowId: " + windowId);
- }
return windowId;
}
}
@@ -534,7 +531,7 @@
if (removedWindowId >= 0) {
if (DEBUG) {
Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid()
- + " with windowId: " + removedWindowId);
+ + " with windowId: " + removedWindowId + " and token: " + window.asBinder());
}
return;
}
@@ -548,7 +545,7 @@
if (DEBUG) {
Slog.i(LOG_TAG, "Removed user connection for pid:" + Binder.getCallingPid()
+ " with windowId: " + removedWindowIdForUser + " and userId:"
- + mUserStates.keyAt(i));
+ + mUserStates.keyAt(i) + " and token: " + window.asBinder());
}
return;
}
@@ -1622,7 +1619,6 @@
public static final int MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER = 1;
public static final int MSG_SEND_STATE_TO_CLIENTS = 2;
public static final int MSG_SEND_CLEARED_STATE_TO_CLIENTS_FOR_USER = 3;
- public static final int MSG_UPDATE_ACTIVE_WINDOW = 4;
public static final int MSG_ANNOUNCE_NEW_USER_IF_NEEDED = 5;
public static final int MSG_UPDATE_INPUT_FILTER = 6;
public static final int MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG = 7;
@@ -1669,12 +1665,6 @@
sendStateToClientsForUser(0, userId);
} break;
- case MSG_UPDATE_ACTIVE_WINDOW: {
- final int windowId = msg.arg1;
- final int eventType = msg.arg2;
- mSecurityPolicy.updateActiveWindow(windowId, eventType);
- } break;
-
case MSG_ANNOUNCE_NEW_USER_IF_NEEDED: {
announceNewUserIfNeeded();
} break;
@@ -3168,7 +3158,7 @@
}
}
- public void updateActiveWindow(int windowId, int eventType) {
+ public void updateActiveWindowLocked(int windowId, int eventType) {
// The active window is either the window that has input focus or
// the window that the user is currently touching. If the user is
// touching a window that does not have input focus as soon as the
@@ -3185,17 +3175,10 @@
// what the focused window is to update the active one.
// The active window also determined events from which
// windows are delivered.
- boolean focusedWindowActive = false;
synchronized (mLock) {
- if (mWindowsForAccessibilityCallback == null) {
- focusedWindowActive = true;
- }
- }
- if (focusedWindowActive) {
- if (windowId == getFocusedWindowId()) {
- synchronized (mLock) {
- mActiveWindowId = windowId;
- }
+ if (mWindowsForAccessibilityCallback == null
+ && windowId == getFocusedWindowId()) {
+ mActiveWindowId = windowId;
}
}
} break;
@@ -3337,7 +3320,9 @@
private int getFocusedWindowId() {
IBinder token = mWindowManagerService.getFocusedWindowToken();
- return findWindowIdLocked(token);
+ synchronized (mLock) {
+ return findWindowIdLocked(token);
+ }
}
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index b84df79..2f56e62 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -158,7 +158,7 @@
final int N = instances.size();
for (int i = 0; i < N; i++) {
Provider p = instances.get(i).provider;
- if (p.info != null && pkg.equals(p.info.provider.getPackageName())) {
+ if (p != null && p.info != null && pkg.equals(p.info.provider.getPackageName())) {
return true;
}
}
@@ -1751,7 +1751,8 @@
for (int i = 0; i < N; i++) {
AppWidgetId id = mAppWidgetIds.get(i);
if (backupTarget.equals(id.host.packageName)
- || backupTarget.equals(id.provider.info.provider.getPackageName())) {
+ || (id.provider != null && backupTarget.equals(
+ id.provider.info.provider.getPackageName()))) {
serializeAppWidgetId(out, id);
}
}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 1a1512f..57c2f92 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -2035,6 +2035,7 @@
BackupState mCurrentState;
// carried information about the current in-flight operation
+ IBackupAgent mAgentBinder;
PackageInfo mCurrentPackage;
File mSavedStateName;
File mBackupDataName;
@@ -2097,6 +2098,7 @@
addBackupTrace(b.toString());
}
+ mAgentBinder = null;
mStatus = BackupConstants.TRANSPORT_OK;
// Sanity check: if the queue is empty we have no work to do.
@@ -2228,6 +2230,7 @@
IApplicationThread.BACKUP_MODE_INCREMENTAL);
addBackupTrace("agent bound; a? = " + (agent != null));
if (agent != null) {
+ mAgentBinder = agent;
mStatus = invokeAgentForBackup(request.packageName, agent, mTransport);
// at this point we'll either get a completion callback from the
// agent, or a timeout message on the main handler. either way, we're
@@ -2253,6 +2256,7 @@
// That means we need to direct to the next state ourselves.
if (mStatus != BackupConstants.TRANSPORT_OK) {
BackupState nextState = BackupState.RUNNING_QUEUE;
+ mAgentBinder = null;
// An agent-level failure means we reenqueue this one agent for
// a later retry, but otherwise proceed normally.
@@ -2274,6 +2278,7 @@
executeNextState(nextState);
} else {
+ // success case
addBackupTrace("expecting completion/timeout callback");
}
}
@@ -2402,14 +2407,52 @@
return BackupConstants.TRANSPORT_OK;
}
+ public void failAgent(IBackupAgent agent, String message) {
+ try {
+ agent.fail(message);
+ } catch (Exception e) {
+ Slog.w(TAG, "Error conveying failure to " + mCurrentPackage.packageName);
+ }
+ }
+
@Override
public void operationComplete() {
- // Okay, the agent successfully reported back to us. The next thing we do is
- // push the app widget state for the app, if any.
+ // Okay, the agent successfully reported back to us!
final String pkgName = mCurrentPackage.packageName;
final long filepos = mBackupDataName.length();
FileDescriptor fd = mBackupData.getFileDescriptor();
try {
+ // If it's a 3rd party app, see whether they wrote any protected keys
+ // and complain mightily if they are attempting shenanigans.
+ if (mCurrentPackage.applicationInfo != null &&
+ (mCurrentPackage.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
+ ParcelFileDescriptor readFd = ParcelFileDescriptor.open(mBackupDataName,
+ ParcelFileDescriptor.MODE_READ_ONLY);
+ BackupDataInput in = new BackupDataInput(readFd.getFileDescriptor());
+ try {
+ while (in.readNextHeader()) {
+ final String key = in.getKey();
+ if (key != null && key.charAt(0) >= 0xff00) {
+ // Not okay: crash them and bail.
+ failAgent(mAgentBinder, "Illegal backup key: " + key);
+ addBackupTrace("illegal key " + key + " from " + pkgName);
+ EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, pkgName,
+ "bad key");
+ mBackupHandler.removeMessages(MSG_TIMEOUT);
+ agentErrorCleanup();
+ // agentErrorCleanup() implicitly executes next state properly
+ return;
+ }
+ in.skipEntityData();
+ }
+ } finally {
+ if (readFd != null) {
+ readFd.close();
+ }
+ }
+ }
+
+ // Piggyback the widget state payload, if any
BackupDataOutput out = new BackupDataOutput(fd);
byte[] widgetState = AppWidgetBackupBridge.getWidgetState(pkgName,
UserHandle.USER_OWNER);
@@ -2434,8 +2477,7 @@
}
}
- // Spin the data off to the
- // transport and proceed with the next stage.
+ // Spin the data off to the transport and proceed with the next stage.
if (MORE_DEBUG) Slog.v(TAG, "operationComplete(): sending data to transport for "
+ pkgName);
mBackupHandler.removeMessages(MSG_TIMEOUT);
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 5fb6405..e69c9a4 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -445,7 +445,7 @@
return;
} else if (Intent.ACTION_USER_ADDED.equals(action)
|| Intent.ACTION_USER_REMOVED.equals(action)) {
- updateRelatedUserIds();
+ updateCurrentProfileIds();
return;
} else {
Slog.w(TAG, "Unexpected intent " + intent);
@@ -689,7 +689,7 @@
// mSettings should be created before buildInputMethodListLocked
mSettings = new InputMethodSettings(
mRes, context.getContentResolver(), mMethodMap, mMethodList, userId);
- updateRelatedUserIds();
+ updateCurrentProfileIds();
mFileManager = new InputMethodFileManager(mMethodMap, userId);
mSwitchingController = new InputMethodSubtypeSwitchingController(mSettings);
mSwitchingController.resetCircularListLocked(context);
@@ -805,7 +805,7 @@
private void switchUserLocked(int newUserId) {
mSettings.setCurrentUserId(newUserId);
- updateRelatedUserIds();
+ updateCurrentProfileIds();
// InputMethodFileManager should be reset when the user is changed
mFileManager = new InputMethodFileManager(mMethodMap, newUserId);
final String defaultImiId = mSettings.getSelectedInputMethod();
@@ -826,14 +826,14 @@
}
}
- void updateRelatedUserIds() {
- List<UserInfo> relatedUsers =
- UserManager.get(mContext).getRelatedUsers(mSettings.getCurrentUserId());
- int[] relatedUserIds = new int[relatedUsers.size()]; // relatedUsers will not be null
- for (int i = 0; i < relatedUserIds.length; i++) {
- relatedUserIds[i] = relatedUsers.get(i).id;
+ void updateCurrentProfileIds() {
+ List<UserInfo> profiles =
+ UserManager.get(mContext).getProfiles(mSettings.getCurrentUserId());
+ int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
+ for (int i = 0; i < currentProfileIds.length; i++) {
+ currentProfileIds[i] = profiles.get(i).id;
}
- mSettings.setRelatedUserIds(relatedUserIds);
+ mSettings.setCurrentProfileIds(currentProfileIds);
}
@Override
@@ -931,7 +931,7 @@
+ mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid()
+ InputMethodUtils.getApiCallStack());
}
- if (uid == Process.SYSTEM_UID || mSettings.isRelatedToOrCurrentUser(userId)) {
+ if (uid == Process.SYSTEM_UID || mSettings.isCurrentProfile(userId)) {
return true;
}
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 19e8083..0d2cee8 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -353,7 +353,7 @@
}
@Override
- public boolean checkVoldPassword(int userId) throws RemoteException {
+ public boolean checkVoldPassword(int userId) throws RemoteException {
if (!mFirstCallToVold) {
return false;
}
@@ -372,11 +372,29 @@
final IMountService service = getMountService();
String password = service.getPassword();
service.clearPassword();
- if (service.getPasswordType() == StorageManager.CRYPT_TYPE_PATTERN) {
- return checkPattern(password, userId);
- } else {
- return checkPassword(password, userId);
+ if (password == null) {
+ return false;
}
+
+ try {
+ if (mLockPatternUtils.isLockPatternEnabled()) {
+ if (checkPattern(password, userId)) {
+ return true;
+ }
+ }
+ } catch (Exception e) {
+ }
+
+ try {
+ if (mLockPatternUtils.isLockPasswordEnabled()) {
+ if (checkPassword(password, userId)) {
+ return true;
+ }
+ }
+ } catch (Exception e) {
+ }
+
+ return false;
}
@Override
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index b6e0d5f..c1d9fbd 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -2084,7 +2084,7 @@
private String toHex(String password) {
if (password == null) {
- return null;
+ return new String();
}
byte[] bytes = password.getBytes(StandardCharsets.UTF_8);
return new String(Hex.encodeHex(bytes));
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b6fc7c3..e9be1d7d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -43,6 +43,7 @@
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.ProcessCpuTracker;
import com.android.internal.os.TransferPipe;
+import com.android.internal.os.Zygote;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.MemInfoReader;
@@ -61,8 +62,6 @@
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
-import dalvik.system.Zygote;
-
import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParser;
@@ -945,6 +944,11 @@
*/
boolean mDidDexOpt;
+ /**
+ * Set if the systemServer made a call to enterSafeMode.
+ */
+ boolean mSafeMode;
+
String mDebugApp = null;
boolean mWaitForDebugger = false;
boolean mDebugTransient = false;
@@ -1015,7 +1019,7 @@
final ActivityThread mSystemThread;
int mCurrentUserId = 0;
- int[] mRelatedUserIds = new int[0]; // Accessed by ActivityStack
+ int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER}; // Accessed by ActivityStack
private UserManagerService mUserManager;
private final class AppDeathRecipient implements IBinder.DeathRecipient {
@@ -1074,7 +1078,7 @@
static final int IMMERSIVE_MODE_LOCK_MSG = 37;
static final int PERSIST_URI_GRANTS_MSG = 38;
static final int REQUEST_ALL_PSS_MSG = 39;
- static final int START_RELATED_USERS_MSG = 40;
+ static final int START_PROFILES_MSG = 40;
static final int UPDATE_TIME = 41;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
@@ -1689,9 +1693,9 @@
requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false);
break;
}
- case START_RELATED_USERS_MSG: {
+ case START_PROFILES_MSG: {
synchronized (ActivityManagerService.this) {
- startRelatedUsersLocked();
+ startProfilesLocked();
}
break;
}
@@ -2737,7 +2741,7 @@
// Run the app in safe mode if its manifest requests so or the
// system is booted in safe mode.
if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
- Zygote.systemInSafeMode == true) {
+ mSafeMode == true) {
debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
}
if ("1".equals(SystemProperties.get("debug.checkjni"))) {
@@ -5204,7 +5208,7 @@
userId);
}
}
- scheduleStartRelatedUsersLocked();
+ scheduleStartProfilesLocked();
}
}
}
@@ -6859,8 +6863,8 @@
maxNum < N ? maxNum : N);
final Set<Integer> includedUsers;
- if ((flags & ActivityManager.RECENT_INCLUDE_RELATED) != 0) {
- includedUsers = getRelatedUsersLocked(userId);
+ if ((flags & ActivityManager.RECENT_INCLUDE_PROFILES) != 0) {
+ includedUsers = getProfileIdsLocked(userId);
} else {
includedUsers = new HashSet<Integer>();
}
@@ -8964,6 +8968,8 @@
} catch (RemoteException e) {
}
}
+
+ mSafeMode = true;
}
}
@@ -16312,19 +16318,19 @@
* user switch happens or when a new related user is started in the
* background.
*/
- private void updateRelatedUserIdsLocked() {
- final List<UserInfo> relatedUsers = getUserManagerLocked().getRelatedUsers(mCurrentUserId);
- int[] relatedUserIds = new int[relatedUsers.size()]; // relatedUsers will not be null
- for (int i = 0; i < relatedUserIds.length; i++) {
- relatedUserIds[i] = relatedUsers.get(i).id;
+ private void updateCurrentProfileIdsLocked() {
+ final List<UserInfo> profiles = getUserManagerLocked().getProfiles(mCurrentUserId);
+ int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
+ for (int i = 0; i < currentProfileIds.length; i++) {
+ currentProfileIds[i] = profiles.get(i).id;
}
- mRelatedUserIds = relatedUserIds;
+ mCurrentProfileIds = currentProfileIds;
}
- private Set getRelatedUsersLocked(int userId) {
+ private Set getProfileIdsLocked(int userId) {
Set userIds = new HashSet<Integer>();
- final List<UserInfo> relatedUsers = getUserManagerLocked().getRelatedUsers(userId);
- for (UserInfo user : relatedUsers) {
+ final List<UserInfo> profiles = getUserManagerLocked().getProfiles(userId);
+ for (UserInfo user : profiles) {
userIds.add(Integer.valueOf(user.id));
}
return userIds;
@@ -16385,15 +16391,15 @@
if (foreground) {
mCurrentUserId = userId;
- updateRelatedUserIdsLocked();
- mWindowManager.setCurrentUser(userId, mRelatedUserIds);
+ updateCurrentProfileIdsLocked();
+ mWindowManager.setCurrentUser(userId, mCurrentProfileIds);
// Once the internal notion of the active user has switched, we lock the device
// with the option to show the user switcher on the keyguard.
mWindowManager.lockNow(null);
} else {
final Integer currentUserIdInt = Integer.valueOf(mCurrentUserId);
- updateRelatedUserIdsLocked();
- mWindowManager.updateRelatedUserIds(mRelatedUserIds);
+ updateCurrentProfileIdsLocked();
+ mWindowManager.setCurrentProfileIds(mCurrentProfileIds);
mUserLru.remove(currentUserIdInt);
mUserLru.add(currentUserIdInt);
}
@@ -16613,20 +16619,21 @@
}
}
- void scheduleStartRelatedUsersLocked() {
- if (!mHandler.hasMessages(START_RELATED_USERS_MSG)) {
- mHandler.sendMessageDelayed(mHandler.obtainMessage(START_RELATED_USERS_MSG),
+ void scheduleStartProfilesLocked() {
+ if (!mHandler.hasMessages(START_PROFILES_MSG)) {
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(START_PROFILES_MSG),
DateUtils.SECOND_IN_MILLIS);
}
}
- void startRelatedUsersLocked() {
- if (DEBUG_MU) Slog.i(TAG_MU, "startRelatedUsersLocked");
- List<UserInfo> relatedUsers = getUserManagerLocked().getRelatedUsers(mCurrentUserId);
- List<UserInfo> toStart = new ArrayList<UserInfo>(relatedUsers.size());
- for (UserInfo relatedUser : relatedUsers) {
- if ((relatedUser.flags & UserInfo.FLAG_INITIALIZED) == UserInfo.FLAG_INITIALIZED) {
- toStart.add(relatedUser);
+ void startProfilesLocked() {
+ if (DEBUG_MU) Slog.i(TAG_MU, "startProfilesLocked");
+ List<UserInfo> profiles = getUserManagerLocked().getProfiles(mCurrentUserId);
+ List<UserInfo> toStart = new ArrayList<UserInfo>(profiles.size());
+ for (UserInfo user : profiles) {
+ if ((user.flags & UserInfo.FLAG_INITIALIZED) == UserInfo.FLAG_INITIALIZED
+ && user.id != mCurrentUserId) {
+ toStart.add(user);
}
}
final int n = toStart.size();
@@ -16635,7 +16642,7 @@
startUserInBackground(toStart.get(i).id);
}
if (i < n) {
- Slog.w(TAG_MU, "More related users than MAX_RUNNING_USERS");
+ Slog.w(TAG_MU, "More profiles than MAX_RUNNING_USERS");
}
}
@@ -16654,7 +16661,7 @@
true, false, MY_PID, Process.SYSTEM_UID, userId);
}
- startRelatedUsersLocked();
+ startProfilesLocked();
int num = mUserLru.size();
int i = 0;
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 3db3a26..b894724 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -341,18 +341,18 @@
}
/**
- * Checks whether the userid is either the current user or a related user.
+ * Checks whether the userid is a profile of the current user.
*/
- private boolean isRelatedToOrCurrentUserLocked(int userId) {
- if (mCurrentUser == userId) return true;
- for (int i = 0; i < mService.mRelatedUserIds.length; i++) {
- if (mService.mRelatedUserIds[i] == userId) return true;
+ private boolean isCurrentProfileLocked(int userId) {
+ if (userId == mCurrentUser) return true;
+ for (int i = 0; i < mService.mCurrentProfileIds.length; i++) {
+ if (mService.mCurrentProfileIds[i] == userId) return true;
}
return false;
}
boolean okToShowLocked(ActivityRecord r) {
- return isRelatedToOrCurrentUserLocked(r.userId)
+ return isCurrentProfileLocked(r.userId)
|| (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0;
}
@@ -571,7 +571,7 @@
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
TaskRecord task = mTaskHistory.get(taskNdx);
- if (!isRelatedToOrCurrentUserLocked(task.userId)) {
+ if (!isCurrentProfileLocked(task.userId)) {
return null;
}
final ArrayList<ActivityRecord> activities = task.mActivities;
@@ -602,7 +602,7 @@
int index = mTaskHistory.size();
for (int i = 0; i < index; ) {
TaskRecord task = mTaskHistory.get(i);
- if (isRelatedToOrCurrentUserLocked(task.userId)) {
+ if (isCurrentProfileLocked(task.userId)) {
if (DEBUG_TASKS) Slog.d(TAG, "switchUserLocked: stack=" + getStackId() +
" moving " + task + " to top");
mTaskHistory.remove(i);
@@ -1189,6 +1189,7 @@
// 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)) {
if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
showHomeBehindStack = true;
@@ -1765,10 +1766,10 @@
mTaskHistory.remove(task);
// Now put task at top.
int stackNdx = mTaskHistory.size();
- if (!isRelatedToOrCurrentUserLocked(task.userId)) {
+ if (!isCurrentProfileLocked(task.userId)) {
// Put non-current user tasks below current user tasks.
while (--stackNdx >= 0) {
- if (!isRelatedToOrCurrentUserLocked(mTaskHistory.get(stackNdx).userId)) {
+ if (!isCurrentProfileLocked(mTaskHistory.get(stackNdx).userId)) {
break;
}
}
@@ -2707,6 +2708,9 @@
if (mResumedActivity == r) {
mResumedActivity = null;
}
+ if (mPausingActivity == r) {
+ mPausingActivity = null;
+ }
if (mService.mFocusedActivity == r) {
mService.mFocusedActivity = null;
}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index b233943..abe362a 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -472,6 +472,7 @@
mTetheredNotification.tickerText = title;
mTetheredNotification.visibility = Notification.VISIBILITY_PUBLIC;
mTetheredNotification.setLatestEventInfo(mContext, title, message, pi);
+ mTetheredNotification.category = Notification.CATEGORY_STATUS;
notificationManager.notifyAsUser(null, mTetheredNotification.icon,
mTetheredNotification, UserHandle.ALL);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecDevice.java
index 9916435..64b51c9 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecDevice.java
@@ -27,8 +27,12 @@
import java.util.List;
/**
- * CecDevice class represents a CEC logical device characterized
- * by its device type. A physical device can contain the functions of
+ * HdmiCecDevice class represents a CEC logical device characterized
+ * by its device type. It is a superclass of those serving concrete device type.
+ * Currently we're interested in playback(one of sources), display(sink) device type
+ * only. The support for the other types like recorder, audio system will come later.
+ *
+ * <p>A physical device can contain the functions of
* more than one logical device, in which case it should create
* as many logical devices as necessary.
*
@@ -41,7 +45,7 @@
*
* <p>Declared as package-private, accessed by HdmiCecService only.
*/
-final class HdmiCecDevice {
+abstract class HdmiCecDevice {
private static final String TAG = "HdmiCecDevice";
private final int mType;
@@ -49,19 +53,38 @@
// List of listeners to the message/event coming to the device.
private final List<IHdmiCecListener> mListeners = new ArrayList<IHdmiCecListener>();
private final Binder mBinder = new Binder();
+ private final HdmiCecService mService;
- private String mName;
private boolean mIsActiveSource;
/**
+ * Factory method that creates HdmiCecDevice instance to the device type.
+ */
+ public static HdmiCecDevice create(HdmiCecService service, int type) {
+ if (type == HdmiCec.DEVICE_PLAYBACK) {
+ return new HdmiCecDevicePlayback(service, type);
+ } else if (type == HdmiCec.DEVICE_TV) {
+ return new HdmiCecDeviceTv(service, type);
+ }
+ return null;
+ }
+
+ /**
* Constructor.
*/
- public HdmiCecDevice(int type) {
+ public HdmiCecDevice(HdmiCecService service, int type) {
+ mService = service;
mType = type;
mIsActiveSource = false;
}
/**
+ * Called right after the class is instantiated. This method can be used to
+ * implement any initialization tasks for the instance.
+ */
+ abstract public void initialize();
+
+ /**
* Return the binder token that identifies this instance.
*/
public Binder getToken() {
@@ -69,6 +92,13 @@
}
/**
+ * Return the service instance.
+ */
+ public HdmiCecService getService() {
+ return mService;
+ }
+
+ /**
* Return the type of this device.
*/
public int getType() {
@@ -76,24 +106,6 @@
}
/**
- * Set the name of the device. The name will be transferred via the message
- * <Set OSD Name> to other HDMI-CEC devices connected through HDMI
- * cables and shown on TV screen to identify the devicie.
- *
- * @param name name of the device
- */
- public void setName(String name) {
- mName = name;
- }
-
- /**
- * Return the name of this device.
- */
- public String getName() {
- return mName;
- }
-
- /**
* Register a listener to be invoked when events occur.
*
* @param listener the listern that will run
@@ -128,6 +140,7 @@
if (opcode == HdmiCec.MESSAGE_ACTIVE_SOURCE) {
mIsActiveSource = false;
}
+
if (mListeners.size() == 0) {
return;
}
@@ -167,4 +180,13 @@
public void setIsActiveSource(boolean state) {
mIsActiveSource = state;
}
+
+ /**
+ * Check if the connected sink device is in powered-on state. The default implementation
+ * simply returns false. Should be overriden by subclass to report the correct state.
+ */
+ public boolean isSinkDeviceOn() {
+ Log.w(TAG, "Not valid for the device type: " + mType);
+ return false;
+ }
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java
new file mode 100644
index 0000000..0310264
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java
@@ -0,0 +1,98 @@
+/*
+ * 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.server.hdmi;
+
+import android.hardware.hdmi.HdmiCec;
+
+/**
+ * Class for the logical device of playback type. Devices such as DVD/Blueray player
+ * that support 'playback' feature are classified as playback device. It is common
+ * that they don't have built-in display, therefore need to talk, stream their contents
+ * to TV/display device which is connected through HDMI cable.
+ *
+ * <p>It closely monitors the status of display device (other devices can be of interest
+ * too, but with much less priority), declares itself as 'active source' to have
+ * display show its output, switch the source state as ordered by display that may be
+ * talking to many other devices connected to it. It also receives commands from display
+ * such as remote control signal, standby, status report, playback mode.
+ *
+ * <p>Declared as package-private, accessed by HdmiCecService only.
+ */
+final class HdmiCecDevicePlayback extends HdmiCecDevice {
+ private static final String TAG = "HdmiCecDevicePlayback";
+
+ private int mSinkDevicePowerStatus;
+
+ /**
+ * Constructor.
+ */
+ public HdmiCecDevicePlayback(HdmiCecService service, int type) {
+ super(service, type);
+ mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_UNKNOWN;
+ }
+
+ @Override
+ public void initialize() {
+ // Playback device tries to obtain the power status of TV/display when created,
+ // and maintains it all through its lifecycle. CEC spec says there is
+ // a maximum 1 second response time. Therefore it should be kept in mind
+ // that there can be as much amount of period of time the power status
+ // of the display remains unknown after the query is sent out.
+ queryTvPowerStatus();
+ }
+
+ private void queryTvPowerStatus() {
+ getService().sendMessage(getType(), HdmiCec.ADDR_TV,
+ HdmiCec.MESSAGE_GIVE_DEVICE_POWER_STATUS, HdmiCecService.EMPTY_PARAM);
+ }
+
+ @Override
+ public void handleMessage(int srcAddress, int dstAddress, int opcode, byte[] params) {
+ // Updates power status of display. The cases are:
+ // 1) Response for the queried power status request arrives. Update the status.
+ // 2) Broadcast or direct <Standby> command from TV, which is sent as TV itself is going
+ // into standby mode too.
+ // 3) Broadcast <Report Physical Address> command from TV, which is sent while it boots up.
+ if (opcode == HdmiCec.MESSAGE_REPORT_POWER_STATUS) {
+ mSinkDevicePowerStatus = params[0];
+ } else if (srcAddress == HdmiCec.ADDR_TV) {
+ if (opcode == HdmiCec.MESSAGE_STANDBY) {
+ mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_STANDBY;
+ } else if (opcode == HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS) {
+ mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_ON;
+ }
+ }
+ super.handleMessage(srcAddress, dstAddress, opcode, params);
+ }
+
+ @Override
+ public void handleHotplug(boolean connected) {
+ // If cable get disconnected sink device becomes unreachable. Switch the status
+ // to unknown, and query the status once the cable gets connected back.
+ if (!connected) {
+ mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_UNKNOWN;
+ } else {
+ queryTvPowerStatus();
+ }
+ super.handleHotplug(connected);
+ }
+
+ @Override
+ public boolean isSinkDeviceOn() {
+ return mSinkDevicePowerStatus == HdmiCec.POWER_STATUS_ON;
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecDeviceTv.java
new file mode 100644
index 0000000..09ff3ca
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiCecDeviceTv.java
@@ -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.
+ */
+
+package com.android.server.hdmi;
+
+/**
+ * Class for logical device of TV type.
+ */
+final class HdmiCecDeviceTv extends HdmiCecDevice {
+ private static final String TAG = "HdmiCecDeviceTv";
+
+ /**
+ * Constructor.
+ */
+ public HdmiCecDeviceTv(HdmiCecService service, int type) {
+ super(service, type);
+ }
+
+ public void initialize() {
+ // TODO: Do the initialization task for TV device here.
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecService.java b/services/core/java/com/android/server/hdmi/HdmiCecService.java
index 36a6e84..aa496c5 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecService.java
@@ -23,6 +23,7 @@
import android.hardware.hdmi.IHdmiCecListener;
import android.hardware.hdmi.IHdmiCecService;
import android.os.Binder;
+import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.TextUtils;
@@ -30,6 +31,7 @@
import android.util.SparseArray;
import com.android.server.SystemService;
+import libcore.util.EmptyArray;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -63,6 +65,8 @@
private static final String PERMISSION = "android.permission.HDMI_CEC";
+ static final byte[] EMPTY_PARAM = EmptyArray.BYTE;
+
public HdmiCecService(Context context) {
super(context);
}
@@ -72,7 +76,12 @@
@Override
public void onStart() {
mNativePtr = nativeInit(this);
- publishBinderService(Context.HDMI_CEC_SERVICE, new BinderService());
+ if (mNativePtr != 0) {
+ // TODO: Consider using a dedicated, configurable identifier for OSD name, maybe from
+ // Settings. It should be ASCII only, not a very long one (limited to 15 chars).
+ setOsdNameLocked(Build.MODEL);
+ publishBinderService(Context.HDMI_CEC_SERVICE, new BinderService());
+ }
}
/**
@@ -84,7 +93,6 @@
// but better be handled in service by turning off the screen
// or putting the device into suspend mode. List up such messages
// and handle them here.
- int type = HdmiCec.getTypeFromAddress(dstAddress);
synchronized (mLock) {
if (dstAddress == HdmiCec.ADDR_BROADCAST) {
for (int i = 0; i < mLogicalDevices.size(); ++i) {
@@ -92,6 +100,7 @@
params);
}
} else {
+ int type = HdmiCec.getTypeFromAddress(dstAddress);
HdmiCecDevice device = mLogicalDevices.get(type);
if (device == null) {
Log.w(TAG, "logical device not found. type: " + type);
@@ -134,22 +143,6 @@
}
/**
- * Called by native when a request for the device OSD name was received.
- * The native part uses the return value to generate the message
- * <Set Osd Name> in response.
- */
- private byte[] getOsdName(int type) {
- // TODO: Consider getting the OSD name from device name instead.
- synchronized (mLock) {
- HdmiCecDevice device = mLogicalDevices.get(type);
- if (device != null) {
- return device.getName().getBytes(Charset.forName("US-ASCII"));
- }
- }
- return null;
- }
-
- /**
* Called by native when a request for the menu language of the device was
* received. The native part uses the return value to generate the message
* <Set Menu Language> in response. The language should be of
@@ -170,8 +163,7 @@
synchronized (mLock) {
for (int i = 0; i < mLogicalDevices.size(); ++i) {
HdmiCecDevice device = mLogicalDevices.valueAt(i);
- pw.println("Device: name=" + device.getName() +
- ", type=" + device.getType() +
+ pw.println("Device: type=" + device.getType() +
", active=" + device.isActiveSource());
}
}
@@ -201,6 +193,15 @@
throw new IllegalArgumentException("Device not found");
}
+ // package-private. Used by HdmiCecDevice and its subclasses only.
+ void sendMessage(int type, int address, int opcode, byte[] params) {
+ nativeSendMessage(mNativePtr, type, address, opcode, params);
+ }
+
+ private void setOsdNameLocked(String name) {
+ nativeSetOsdName(mNativePtr, name.getBytes(Charset.forName("US-ASCII")));
+ }
+
private final class ListenerRecord implements IBinder.DeathRecipient {
private final IHdmiCecListener mListener;
private final int mType;
@@ -244,8 +245,12 @@
Log.e(TAG, "Logical address was not allocated");
return null;
} else {
- device = new HdmiCecDevice(type);
- device.setName(HdmiCec.getDefaultDeviceName(address));
+ device = HdmiCecDevice.create(HdmiCecService.this, type);
+ if (device == null) {
+ Log.e(TAG, "Device type not supported yet.");
+ return null;
+ }
+ device.initialize();
mLogicalDevices.put(type, device);
}
}
@@ -268,24 +273,18 @@
}
@Override
- public void setOsdName(IBinder b, String name) {
- enforceAccessPermission();
- if (TextUtils.isEmpty(name)) {
- throw new IllegalArgumentException("name must not be null");
- }
- synchronized (mLock) {
- HdmiCecDevice device = getLogicalDeviceLocked(b);
- device.setName(name);
- }
- }
-
- @Override
public void sendActiveSource(IBinder b) {
enforceAccessPermission();
synchronized (mLock) {
HdmiCecDevice device = getLogicalDeviceLocked(b);
device.setIsActiveSource(true);
- nativeSendActiveSource(mNativePtr, device.getType());
+ int physicalAddress = nativeGetPhysicalAddress(mNativePtr);
+ byte[] param = new byte[] {
+ (byte) ((physicalAddress >> 8) & 0xff),
+ (byte) (physicalAddress & 0xff)
+ };
+ nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_BROADCAST,
+ HdmiCec.MESSAGE_ACTIVE_SOURCE, param);
}
}
@@ -295,7 +294,8 @@
synchronized (mLock) {
HdmiCecDevice device = getLogicalDeviceLocked(b);
device.setIsActiveSource(false);
- nativeSendInactiveSource(mNativePtr, device.getType());
+ nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_BROADCAST,
+ HdmiCec.MESSAGE_INACTIVE_SOURCE, EMPTY_PARAM);
}
}
@@ -304,7 +304,8 @@
enforceAccessPermission();
synchronized (mLock) {
HdmiCecDevice device = getLogicalDeviceLocked(b);
- nativeSendImageViewOn(mNativePtr, device.getType());
+ nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_TV,
+ HdmiCec.MESSAGE_IMAGE_VIEW_ON, EMPTY_PARAM);
}
}
@@ -313,16 +314,17 @@
enforceAccessPermission();
synchronized (mLock) {
HdmiCecDevice device = getLogicalDeviceLocked(b);
- nativeSendTextViewOn(mNativePtr, device.getType());
+ nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_TV,
+ HdmiCec.MESSAGE_TEXT_VIEW_ON, EMPTY_PARAM);
}
}
@Override
- public void sendGiveDevicePowerStatus(IBinder b, int address) {
+ public boolean isTvOn(IBinder b) {
enforceAccessPermission();
synchronized (mLock) {
HdmiCecDevice device = getLogicalDeviceLocked(b);
- nativeSendGiveDevicePowerStatus(mNativePtr, device.getType(), address);
+ return device.isSinkDeviceOn();
}
}
@@ -366,7 +368,8 @@
if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
pw.println("Permission denial: can't dump HdmiCecService from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+ + " without permission " + android.Manifest.permission.DUMP);
return;
}
final long ident = Binder.clearCallingIdentity();
@@ -382,10 +385,6 @@
private static native void nativeRemoveLogicalAddress(long handler, int deviceType);
private static native void nativeSendMessage(long handler, int deviceType, int destination,
int opcode, byte[] params);
- private static native void nativeSendActiveSource(long handler, int deviceType);
- private static native void nativeSendInactiveSource(long handler, int deviceType);
- private static native void nativeSendImageViewOn(long handler, int deviceType);
- private static native void nativeSendTextViewOn(long handler, int deviceType);
- private static native void nativeSendGiveDevicePowerStatus(long handler, int deviceType,
- int address);
+ private static native int nativeGetPhysicalAddress(long handler);
+ private static native void nativeSetOsdName(long handler, byte[] name);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 7c2de8b..3b6d288 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -65,8 +65,8 @@
import android.service.notification.StatusBarNotification;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.AtomicFile;
-import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -76,9 +76,9 @@
import android.widget.Toast;
import com.android.internal.R;
-
import com.android.internal.notification.NotificationScorer;
import com.android.server.EventLogTags;
+import com.android.server.notification.NotificationUsageStats.SingleNotificationStats;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.SystemService;
import com.android.server.lights.Light;
@@ -169,7 +169,8 @@
// used as a mutex for access to all active notifications & listeners
final ArrayList<NotificationRecord> mNotificationList =
new ArrayList<NotificationRecord>();
-
+ final ArrayMap<String, NotificationRecord> mNotificationsByKey =
+ new ArrayMap<String, NotificationRecord>();
final ArrayList<ToastRecord> mToastQueue = new ArrayList<ToastRecord>();
ArrayList<NotificationRecord> mLights = new ArrayList<NotificationRecord>();
@@ -205,6 +206,8 @@
final ArrayList<NotificationScorer> mScorers = new ArrayList<NotificationScorer>();
+ private final NotificationUsageStats mUsageStats = new NotificationUsageStats();
+
private int mZenMode;
// temporary, until we update apps to provide metadata
private static final Set<String> CALL_PACKAGES = new HashSet<String>(Arrays.asList(
@@ -216,8 +219,8 @@
));
private static final String EXTRA_INTERCEPT = "android.intercept";
- // Users related to the current user.
- final protected SparseArray<UserInfo> mRelatedUsers = new SparseArray<UserInfo>();
+ // Profiles of the current user.
+ final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();
private static final int MY_UID = Process.myUid();
private static final int MY_PID = Process.myPid();
@@ -661,6 +664,7 @@
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
+ boolean added = false;
synchronized (mNotificationList) {
mServicesBinding.remove(servicesBindingTag);
try {
@@ -669,11 +673,20 @@
= new NotificationListenerInfo(
mListener, name, userid, this);
service.linkToDeath(info, 0);
- mListeners.add(info);
+ added = mListeners.add(info);
} catch (RemoteException e) {
// already dead
}
}
+ if (added) {
+ final String[] keys =
+ getActiveNotificationKeysFromListener(mListener);
+ try {
+ mListener.onListenerConnected(keys);
+ } catch (RemoteException e) {
+ // we tried
+ }
+ }
}
@Override
@@ -763,7 +776,7 @@
}
}
- private NotificationListenerInfo checkListenerToken(INotificationListener listener) {
+ private NotificationListenerInfo checkListenerTokenLocked(INotificationListener listener) {
checkNullListener(listener);
final IBinder token = listener.asBinder();
final int N = mListeners.size();
@@ -781,6 +794,7 @@
public static final class NotificationRecord
{
final StatusBarNotification sbn;
+ final SingleNotificationStats stats = new SingleNotificationStats();
IBinder statusBarKey;
NotificationRecord(StatusBarNotification sbn)
@@ -799,6 +813,7 @@
pw.println(prefix + " icon=0x" + Integer.toHexString(notification.icon)
+ " / " + idDebugString(baseContext, sbn.getPackageName(), notification.icon));
pw.println(prefix + " pri=" + notification.priority + " score=" + sbn.getScore());
+ pw.println(prefix + " key=" + sbn.getKey());
pw.println(prefix + " contentIntent=" + notification.contentIntent);
pw.println(prefix + " deleteIntent=" + notification.deleteIntent);
pw.println(prefix + " tickerText=" + notification.tickerText);
@@ -850,15 +865,17 @@
}
pw.println(prefix + " }");
}
+ pw.println(prefix + " stats=" + stats.toString());
}
@Override
public final String toString() {
return String.format(
- "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s score=%d: %s)",
+ "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s score=%d key=%s: %s)",
System.identityHashCode(this),
this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(),
- this.sbn.getTag(), this.sbn.getScore(), this.sbn.getNotification());
+ this.sbn.getTag(), this.sbn.getScore(), this.sbn.getKey(),
+ this.sbn.getNotification());
}
}
@@ -927,7 +944,9 @@
@Override
public void onClearAll(int callingUid, int callingPid, int userId) {
- cancelAll(callingUid, callingPid, userId, REASON_DELEGATE_CANCEL_ALL, null);
+ synchronized (mNotificationList) {
+ cancelAllLocked(callingUid, callingPid, userId, REASON_DELEGATE_CANCEL_ALL, null);
+ }
}
@Override
@@ -1101,9 +1120,9 @@
} else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
// reload per-user settings
mSettingsObserver.update(null);
- updateRelatedUserCache(context);
+ updateCurrentProfilesCache(context);
} else if (action.equals(Intent.ACTION_USER_ADDED)) {
- updateRelatedUserCache(context);
+ updateCurrentProfilesCache(context);
}
}
};
@@ -1242,7 +1261,6 @@
getContext().registerReceiver(mIntentReceiver, sdFilter);
mSettingsObserver = new SettingsObserver(mHandler);
- mSettingsObserver.observe();
// spin up NotificationScorers
String[] notificationScorerNames = resources.getStringArray(
@@ -1297,8 +1315,10 @@
// Grab our optional AudioService
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
- // make sure our listener services are properly bound
- rebindListenerServices();
+ } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
+ // This observer will force an update when observe is called, causing us to
+ // bind to listener services.
+ mSettingsObserver.observe();
}
}
@@ -1551,19 +1571,40 @@
* @param token The binder for the listener, to check that the caller is allowed
*/
@Override
- public void cancelAllNotificationsFromListener(INotificationListener token) {
- NotificationListenerInfo info = checkListenerToken(token);
+ public void cancelNotificationsFromListener(INotificationListener token, String[] keys) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
long identity = Binder.clearCallingIdentity();
try {
- cancelAll(callingUid, callingPid, info.userid,
- REASON_LISTENER_CANCEL_ALL, info);
+ synchronized (mNotificationList) {
+ final NotificationListenerInfo info = checkListenerTokenLocked(token);
+ if (keys != null) {
+ final int N = keys.length;
+ for (int i = 0; i < N; i++) {
+ NotificationRecord r = mNotificationsByKey.get(keys[i]);
+ if (r != null) {
+ cancelNotificationFromListenerLocked(info, callingUid, callingPid,
+ r.sbn.getPackageName(), r.sbn.getTag(), r.sbn.getId());
+ }
+ }
+ } else {
+ cancelAllLocked(callingUid, callingPid, info.userid,
+ REASON_LISTENER_CANCEL_ALL, info);
+ }
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
}
+ private void cancelNotificationFromListenerLocked(NotificationListenerInfo info,
+ int callingUid, int callingPid, String pkg, String tag, int id) {
+ cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
+ Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
+ true,
+ info.userid, REASON_LISTENER_CANCEL, info);
+ }
+
/**
* Allow an INotificationListener to simulate clearing (dismissing) a single notification.
*
@@ -1574,15 +1615,15 @@
@Override
public void cancelNotificationFromListener(INotificationListener token, String pkg,
String tag, int id) {
- NotificationListenerInfo info = checkListenerToken(token);
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
long identity = Binder.clearCallingIdentity();
try {
- cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
- Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
- true,
- info.userid, REASON_LISTENER_CANCEL, info);
+ synchronized (mNotificationList) {
+ final NotificationListenerInfo info = checkListenerTokenLocked(token);
+ cancelNotificationFromListenerLocked(info, callingUid, callingPid,
+ pkg, tag, id);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1597,21 +1638,35 @@
*/
@Override
public StatusBarNotification[] getActiveNotificationsFromListener(
- INotificationListener token) {
- NotificationListenerInfo info = checkListenerToken(token);
-
- StatusBarNotification[] result = new StatusBarNotification[0];
- ArrayList<StatusBarNotification> list = new ArrayList<StatusBarNotification>();
+ INotificationListener token, String[] keys) {
synchronized (mNotificationList) {
- final int N = mNotificationList.size();
- for (int i=0; i<N; i++) {
- StatusBarNotification sbn = mNotificationList.get(i).sbn;
- if (info.enabledAndUserMatches(sbn)) {
- list.add(sbn);
+ final NotificationListenerInfo info = checkListenerTokenLocked(token);
+ final ArrayList<StatusBarNotification> list
+ = new ArrayList<StatusBarNotification>();
+ if (keys == null) {
+ final int N = mNotificationList.size();
+ for (int i=0; i<N; i++) {
+ StatusBarNotification sbn = mNotificationList.get(i).sbn;
+ if (info.enabledAndUserMatches(sbn)) {
+ list.add(sbn);
+ }
+ }
+ } else {
+ final int N = keys.length;
+ for (int i=0; i<N; i++) {
+ NotificationRecord r = mNotificationsByKey.get(keys[i]);
+ if (r != null && info.enabledAndUserMatches(r.sbn)) {
+ list.add(r.sbn);
+ }
}
}
+ return list.toArray(new StatusBarNotification[list.size()]);
}
- return list.toArray(result);
+ }
+
+ @Override
+ public String[] getActiveNotificationKeysFromListener(INotificationListener token) {
+ return NotificationManagerService.this.getActiveNotificationKeysFromListener(token);
}
@Override
@@ -1628,6 +1683,21 @@
}
};
+ private String[] getActiveNotificationKeysFromListener(INotificationListener token) {
+ synchronized (mNotificationList) {
+ final NotificationListenerInfo info = checkListenerTokenLocked(token);
+ final ArrayList<String> keys = new ArrayList<String>();
+ final int N = mNotificationList.size();
+ for (int i=0; i<N; i++) {
+ final StatusBarNotification sbn = mNotificationList.get(i).sbn;
+ if (info.enabledAndUserMatches(sbn)) {
+ keys.add(sbn.getKey());
+ }
+ }
+ return keys.toArray(new String[keys.size()]);
+ }
+ }
+
void dumpImpl(PrintWriter pw) {
pw.println("Current Notification Manager state:");
@@ -1693,6 +1763,9 @@
}
}
+ pw.println("\n Usage Stats:");
+ mUsageStats.dump(pw, " ");
+
}
}
@@ -1840,15 +1913,21 @@
int index = indexOfNotificationLocked(pkg, tag, id, userId);
if (index < 0) {
mNotificationList.add(r);
+ mUsageStats.registerPostedByApp(r);
} else {
old = mNotificationList.remove(index);
mNotificationList.add(index, r);
+ mUsageStats.registerUpdatedByApp(r);
// Make sure we don't lose the foreground service state.
if (old != null) {
notification.flags |=
old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;
}
}
+ if (old != null) {
+ mNotificationsByKey.remove(old.sbn.getKey());
+ }
+ mNotificationsByKey.put(n.getKey(), r);
// Ensure if this is a foreground service that the proper additional
// flags are set.
@@ -2231,7 +2310,7 @@
manager.sendAccessibilityEvent(event);
}
- private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete) {
+ private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete, int reason) {
// tell the app
if (sendDelete) {
if (r.getNotification().deleteIntent != null) {
@@ -2290,6 +2369,26 @@
mLedNotification = null;
}
+ // Record usage stats
+ switch (reason) {
+ case REASON_DELEGATE_CANCEL:
+ case REASON_DELEGATE_CANCEL_ALL:
+ case REASON_LISTENER_CANCEL:
+ case REASON_LISTENER_CANCEL_ALL:
+ mUsageStats.registerDismissedByUser(r);
+ break;
+ case REASON_NOMAN_CANCEL:
+ case REASON_NOMAN_CANCEL_ALL:
+ mUsageStats.registerRemovedByApp(r);
+ break;
+ case REASON_DELEGATE_CLICK:
+ mUsageStats.registerCancelDueToClick(r);
+ break;
+ default:
+ mUsageStats.registerCancelUnknown(r);
+ break;
+ }
+
// Save it for users of getHistoricalNotifications()
mArchive.record(r.sbn);
}
@@ -2318,6 +2417,12 @@
if (index >= 0) {
NotificationRecord r = mNotificationList.get(index);
+ // Ideally we'd do this in the caller of this method. However, that would
+ // require the caller to also find the notification.
+ if (reason == REASON_DELEGATE_CLICK) {
+ mUsageStats.registerClickedByUser(r);
+ }
+
if ((r.getNotification().flags & mustHaveFlags) != mustHaveFlags) {
return;
}
@@ -2326,8 +2431,9 @@
}
mNotificationList.remove(index);
+ mNotificationsByKey.remove(r.sbn.getKey());
- cancelNotificationLocked(r, sendDelete);
+ cancelNotificationLocked(r, sendDelete, reason);
updateLightsLocked();
}
}
@@ -2352,12 +2458,12 @@
/**
* Determine whether the userId applies to the notification in question, either because
* they match exactly, or one of them is USER_ALL (which is treated as a wildcard) or
- * because it matches a related user.
+ * because it matches one of the users profiles.
*/
- private boolean notificationMatchesUserIdOrRelated(NotificationRecord r, int userId) {
- synchronized (mRelatedUsers) {
+ private boolean notificationMatchesCurrentProfiles(NotificationRecord r, int userId) {
+ synchronized (mCurrentProfiles) {
return notificationMatchesUserId(r, userId)
- || mRelatedUsers.get(r.getUserId()) != null;
+ || mCurrentProfiles.get(r.getUserId()) != null;
}
}
@@ -2398,7 +2504,8 @@
return true;
}
mNotificationList.remove(i);
- cancelNotificationLocked(r, false);
+ mNotificationsByKey.remove(r.sbn.getKey());
+ cancelNotificationLocked(r, false, reason);
}
if (canceledSomething) {
updateLightsLocked();
@@ -2445,29 +2552,27 @@
}
}
- void cancelAll(int callingUid, int callingPid, int userId, int reason,
+ void cancelAllLocked(int callingUid, int callingPid, int userId, int reason,
NotificationListenerInfo listener) {
EventLogTags.writeNotificationCancelAll(callingUid, callingPid,
null, userId, 0, 0, reason,
listener == null ? null : listener.component.toShortString());
- synchronized (mNotificationList) {
- final int N = mNotificationList.size();
- for (int i=N-1; i>=0; i--) {
- NotificationRecord r = mNotificationList.get(i);
- if (!notificationMatchesUserIdOrRelated(r, userId)) {
- continue;
- }
-
- if ((r.getFlags() & (Notification.FLAG_ONGOING_EVENT
- | Notification.FLAG_NO_CLEAR)) == 0) {
- mNotificationList.remove(i);
- cancelNotificationLocked(r, true);
- }
+ final int N = mNotificationList.size();
+ for (int i=N-1; i>=0; i--) {
+ NotificationRecord r = mNotificationList.get(i);
+ if (!notificationMatchesCurrentProfiles(r, userId)) {
+ continue;
}
- updateLightsLocked();
+ if ((r.getFlags() & (Notification.FLAG_ONGOING_EVENT
+ | Notification.FLAG_NO_CLEAR)) == 0) {
+ mNotificationList.remove(i);
+ mNotificationsByKey.remove(r.sbn.getKey());
+ cancelNotificationLocked(r, true, reason);
+ }
}
+ updateLightsLocked();
}
// lock on mNotificationList
@@ -2557,7 +2662,7 @@
exceptionPackages);
// alarm restrictions
- final boolean muteAlarms = mZenMode == Settings.Global.ZEN_MODE_FULL;
+ final boolean muteAlarms = false; // TODO until we save user config
mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, AudioManager.STREAM_ALARM,
muteAlarms ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
exceptionPackages);
@@ -2571,15 +2676,15 @@
exceptionPackages);
}
- private void updateRelatedUserCache(Context context) {
+ private void updateCurrentProfilesCache(Context context) {
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
int currentUserId = ActivityManager.getCurrentUser();
if (userManager != null) {
- List<UserInfo> relatedUsers = userManager.getRelatedUsers(currentUserId);
- synchronized (mRelatedUsers) {
- mRelatedUsers.clear();
- for (UserInfo related : relatedUsers) {
- mRelatedUsers.put(related.id, related);
+ List<UserInfo> profiles = userManager.getProfiles(currentUserId);
+ synchronized (mCurrentProfiles) {
+ mCurrentProfiles.clear();
+ for (UserInfo user : profiles) {
+ mCurrentProfiles.put(user.id, user);
}
}
}
@@ -2594,10 +2699,8 @@
}
private boolean shouldIntercept(String pkg, Notification n) {
- if (mZenMode == Settings.Global.ZEN_MODE_LIMITED) {
+ if (mZenMode != Settings.Global.ZEN_MODE_OFF) {
return !isAlarm(pkg, n);
- } else if (mZenMode == Settings.Global.ZEN_MODE_FULL) {
- return true;
}
return false;
}
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
new file mode 100644
index 0000000..d9e2b91
--- /dev/null
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -0,0 +1,277 @@
+/*
+ * 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.server.notification;
+
+import com.android.server.notification.NotificationManagerService.NotificationRecord;
+
+import android.os.SystemClock;
+import android.service.notification.StatusBarNotification;
+
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Keeps track of notification activity, display, and user interaction.
+ *
+ * <p>This class receives signals from NoMan and keeps running stats of
+ * notification usage. Some metrics are updated as events occur. Others, namely
+ * those involving durations, are updated as the notification is canceled.</p>
+ *
+ * <p>This class is thread-safe.</p>
+ *
+ * {@hide}
+ */
+public class NotificationUsageStats {
+
+ // Guarded by synchronized(this).
+ private final Map<String, AggregatedStats> mStats = new HashMap<String, AggregatedStats>();
+
+ /**
+ * Called when a notification has been posted.
+ */
+ public synchronized void registerPostedByApp(NotificationRecord notification) {
+ notification.stats.posttimeElapsedMs = SystemClock.elapsedRealtime();
+ for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
+ stats.numPostedByApp++;
+ }
+ }
+
+ /**
+ * Called when a notification has been updated.
+ */
+ public void registerUpdatedByApp(NotificationRecord notification) {
+ for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
+ stats.numUpdatedByApp++;
+ }
+ }
+
+ /**
+ * Called when the originating app removed the notification programmatically.
+ */
+ public synchronized void registerRemovedByApp(NotificationRecord notification) {
+ for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
+ stats.numRemovedByApp++;
+ stats.collect(notification.stats);
+ }
+ }
+
+ /**
+ * Called when the user dismissed the notification via the UI.
+ */
+ public synchronized void registerDismissedByUser(NotificationRecord notification) {
+ notification.stats.onDismiss();
+ for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
+ stats.numDismissedByUser++;
+ stats.collect(notification.stats);
+ }
+ }
+
+ /**
+ * Called when the user clicked the notification in the UI.
+ */
+ public synchronized void registerClickedByUser(NotificationRecord notification) {
+ notification.stats.onClick();
+ for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
+ stats.numClickedByUser++;
+ }
+ }
+
+ /**
+ * Called when the notification is canceled because the user clicked it.
+ *
+ * <p>Called after {@link #registerClickedByUser(NotificationRecord)}.</p>
+ */
+ public synchronized void registerCancelDueToClick(NotificationRecord notification) {
+ // No explicit stats for this (the click has already been registered in
+ // registerClickedByUser), just make sure the single notification stats
+ // are folded up into aggregated stats.
+ for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
+ stats.collect(notification.stats);
+ }
+ }
+
+ /**
+ * Called when the notification is canceled due to unknown reasons.
+ *
+ * <p>Called for notifications of apps being uninstalled, for example.</p>
+ */
+ public synchronized void registerCancelUnknown(NotificationRecord notification) {
+ // Fold up individual stats.
+ for (AggregatedStats stats : getAggregatedStatsLocked(notification)) {
+ stats.collect(notification.stats);
+ }
+ }
+
+ // Locked by this.
+ private AggregatedStats[] getAggregatedStatsLocked(NotificationRecord record) {
+ StatusBarNotification n = record.sbn;
+
+ String user = String.valueOf(n.getUserId());
+ String userPackage = user + ":" + n.getPackageName();
+
+ // TODO: Use pool of arrays.
+ return new AggregatedStats[] {
+ getOrCreateAggregatedStatsLocked(user),
+ getOrCreateAggregatedStatsLocked(userPackage),
+ getOrCreateAggregatedStatsLocked(n.getKey()),
+ };
+ }
+
+ // Locked by this.
+ private AggregatedStats getOrCreateAggregatedStatsLocked(String key) {
+ AggregatedStats result = mStats.get(key);
+ if (result == null) {
+ result = new AggregatedStats(key);
+ mStats.put(key, result);
+ }
+ return result;
+ }
+
+ public synchronized void dump(PrintWriter pw, String indent) {
+ for (AggregatedStats as : mStats.values()) {
+ as.dump(pw, indent);
+ }
+ }
+
+ /**
+ * Aggregated notification stats.
+ */
+ private static class AggregatedStats {
+ public final String key;
+
+ // ---- Updated as the respective events occur.
+ public int numPostedByApp;
+ public int numUpdatedByApp;
+ public int numRemovedByApp;
+ public int numClickedByUser;
+ public int numDismissedByUser;
+
+ // ---- Updated when a notification is canceled.
+ public final Aggregate posttimeMs = new Aggregate();
+ public final Aggregate posttimeToDismissMs = new Aggregate();
+ public final Aggregate posttimeToFirstClickMs = new Aggregate();
+
+ public AggregatedStats(String key) {
+ this.key = key;
+ }
+
+ public void collect(SingleNotificationStats singleNotificationStats) {
+ posttimeMs.addSample(
+ SystemClock.elapsedRealtime() - singleNotificationStats.posttimeElapsedMs);
+ if (singleNotificationStats.posttimeToDismissMs >= 0) {
+ posttimeToDismissMs.addSample(singleNotificationStats.posttimeToDismissMs);
+ }
+ if (singleNotificationStats.posttimeToFirstClickMs >= 0) {
+ posttimeToFirstClickMs.addSample(singleNotificationStats.posttimeToFirstClickMs);
+ }
+ }
+
+ public void dump(PrintWriter pw, String indent) {
+ pw.println(toStringWithIndent(indent));
+ }
+
+ @Override
+ public String toString() {
+ return toStringWithIndent("");
+ }
+
+ private String toStringWithIndent(String indent) {
+ return indent + "AggregatedStats{\n" +
+ indent + " key='" + key + "',\n" +
+ indent + " numPostedByApp=" + numPostedByApp + ",\n" +
+ indent + " numUpdatedByApp=" + numUpdatedByApp + ",\n" +
+ indent + " numRemovedByApp=" + numRemovedByApp + ",\n" +
+ indent + " numClickedByUser=" + numClickedByUser + ",\n" +
+ indent + " numDismissedByUser=" + numDismissedByUser + ",\n" +
+ indent + " posttimeMs=" + posttimeMs + ",\n" +
+ indent + " posttimeToDismissMs=" + posttimeToDismissMs + ",\n" +
+ indent + " posttimeToFirstClickMs=" + posttimeToFirstClickMs + ",\n" +
+ indent + "}";
+ }
+ }
+
+ /**
+ * Tracks usage of an individual notification that is currently active.
+ */
+ public static class SingleNotificationStats {
+ /** SystemClock.elapsedRealtime() when the notification was posted. */
+ public long posttimeElapsedMs = -1;
+ /** Elapsed time since the notification was posted until it was first clicked, or -1. */
+ public long posttimeToFirstClickMs = -1;
+ /** Elpased time since the notification was posted until it was dismissed by the user. */
+ public long posttimeToDismissMs = -1;
+
+ /**
+ * Called when the user clicked the notification.
+ */
+ public void onClick() {
+ if (posttimeToFirstClickMs < 0) {
+ posttimeToFirstClickMs = SystemClock.elapsedRealtime() - posttimeElapsedMs;
+ }
+ }
+
+ /**
+ * Called when the user removed the notification.
+ */
+ public void onDismiss() {
+ if (posttimeToDismissMs < 0) {
+ posttimeToDismissMs = SystemClock.elapsedRealtime() - posttimeElapsedMs;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "SingleNotificationStats{" +
+ "posttimeElapsedMs=" + posttimeElapsedMs +
+ ", posttimeToFirstClickMs=" + posttimeToFirstClickMs +
+ ", posttimeToDismissMs=" + posttimeToDismissMs +
+ '}';
+ }
+ }
+
+ /**
+ * Aggregates long samples to sum and averages.
+ */
+ public static class Aggregate {
+ long numSamples;
+ double avg;
+ double sum2;
+ double var;
+
+ public void addSample(long sample) {
+ // Welford's "Method for Calculating Corrected Sums of Squares"
+ // http://www.jstor.org/stable/1266577?seq=2
+ numSamples++;
+ final double n = numSamples;
+ final double delta = sample - avg;
+ avg += (1.0 / n) * delta;
+ sum2 += ((n - 1) / n) * delta * delta;
+ final double divisor = numSamples == 1 ? 1.0 : n - 1.0;
+ var = sum2 / divisor;
+ }
+
+ @Override
+ public String toString() {
+ return "Aggregate{" +
+ "numSamples=" + numSamples +
+ ", avg=" + avg +
+ ", var=" + var +
+ '}';
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index ae1cfab..ff816ea 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -407,7 +407,14 @@
return execute(builder.toString());
}
- public boolean restoreconData() {
- return (execute("restorecondata") == 0);
+ public boolean restoreconData(String pkgName, String seinfo, int uid) {
+ StringBuilder builder = new StringBuilder("restorecondata");
+ builder.append(' ');
+ builder.append(pkgName);
+ builder.append(' ');
+ builder.append(seinfo != null ? seinfo : "!");
+ builder.append(' ');
+ builder.append(uid);
+ return (execute(builder.toString()) == 0);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a01c586..dd22b2d 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -69,6 +69,7 @@
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageInstallObserver;
+import android.content.pm.IPackageInstallObserver2;
import android.content.pm.IPackageManager;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
@@ -340,7 +341,7 @@
// Lock for state used when installing and doing other long running
// operations. Methods that must be called with this lock held have
- // the prefix "LI".
+ // the suffix "LI".
final Object mInstallLock = new Object();
// These are the directories in the 3rd party applications installed dir
@@ -401,6 +402,9 @@
// If mac_permissions.xml was found for seinfo labeling.
boolean mFoundPolicyFile;
+ // If a recursive restorecon of /data/data/<pkg> is needed.
+ private boolean mShouldRestoreconData = SELinuxMMAC.shouldRestorecon();
+
// All available activities, for your resolving pleasure.
final ActivityIntentResolver mActivities =
new ActivityIntentResolver();
@@ -696,7 +700,7 @@
// Just post MCS_BOUND message to trigger processing
// of next pending install.
if (DEBUG_SD_INSTALL) Log.i(TAG,
- "Posting MCS_BOUND for next woek");
+ "Posting MCS_BOUND for next work");
mHandler.sendEmptyMessage(MCS_BOUND);
}
}
@@ -916,6 +920,14 @@
Slog.i(TAG, "Observer no longer exists.");
}
}
+ if (args.observer2 != null) {
+ try {
+ Bundle extras = extrasForInstallResult(res);
+ args.observer2.packageInstalled(res.name, extras, res.returnCode);
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Observer no longer exists.");
+ }
+ }
} else {
Slog.e(TAG, "Bogus post-install token " + msg.arg1);
}
@@ -1044,6 +1056,21 @@
}
}
+ Bundle extrasForInstallResult(PackageInstalledInfo res) {
+ Bundle extras = null;
+ switch (res.returnCode) {
+ case PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION: {
+ extras = new Bundle();
+ extras.putString(PackageManager.EXTRA_FAILURE_EXISTING_PERMISSION,
+ res.origPermission);
+ extras.putString(PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE,
+ res.origPackage);
+ break;
+ }
+ }
+ return extras;
+ }
+
void scheduleWriteSettingsLocked() {
if (!mHandler.hasMessages(WRITE_SETTINGS)) {
mHandler.sendEmptyMessageDelayed(WRITE_SETTINGS, WRITE_SETTINGS_DELAY);
@@ -1512,13 +1539,6 @@
// can downgrade to reader
mSettings.writeLPr();
- if (SELinuxMMAC.shouldRestorecon()) {
- Slog.i(TAG, "Relabeling of /data/data and /data/user issued.");
- if (mInstaller.restoreconData()) {
- SELinuxMMAC.setRestoreconDone();
- }
- }
-
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
@@ -4763,6 +4783,11 @@
}
}
pkg.applicationInfo.dataDir = dataPath.getPath();
+ if (mShouldRestoreconData) {
+ Slog.i(TAG, "SELinux relabeling of " + pkg.packageName + " issued.");
+ mInstaller.restoreconData(pkg.packageName, pkg.applicationInfo.seinfo,
+ pkg.applicationInfo.uid);
+ }
} else {
if (DEBUG_PACKAGE_SCANNING) {
if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
@@ -6772,18 +6797,24 @@
private final boolean mIsPrivileged;
}
+ /*
+ * The old-style observer methods all just trampoline to the newer signature with
+ * expanded install observer API. The older API continues to work but does not
+ * supply the additional details of the Observer2 API.
+ */
+
/* Called when a downloaded package installation has been confirmed by the user */
public void installPackage(
final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
- installPackage(packageURI, observer, flags, null);
+ installPackageEtc(packageURI, observer, null, flags, null);
}
/* Called when a downloaded package installation has been confirmed by the user */
public void installPackage(
final Uri packageURI, final IPackageInstallObserver observer, final int flags,
final String installerPackageName) {
- installPackageWithVerification(packageURI, observer, flags, installerPackageName, null,
- null, null);
+ installPackageWithVerificationEtc(packageURI, observer, null, flags,
+ installerPackageName, null, null, null);
}
@Override
@@ -6792,20 +6823,67 @@
ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
VerificationParams verificationParams = new VerificationParams(verificationURI, null, null,
VerificationParams.NO_UID, manifestDigest);
- installPackageWithVerificationAndEncryption(packageURI, observer, flags,
+ installPackageWithVerificationAndEncryptionEtc(packageURI, observer, null, flags,
installerPackageName, verificationParams, encryptionParams);
}
public void installPackageWithVerificationAndEncryption(Uri packageURI,
IPackageInstallObserver observer, int flags, String installerPackageName,
VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+ installPackageWithVerificationAndEncryptionEtc(packageURI, observer, null, flags,
+ installerPackageName, verificationParams, encryptionParams);
+ }
+
+ /*
+ * And here are the "live" versions that take both observer arguments
+ */
+ public void installPackageEtc(
+ final Uri packageURI, final IPackageInstallObserver observer,
+ IPackageInstallObserver2 observer2, final int flags) {
+ installPackageEtc(packageURI, observer, observer2, flags, null);
+ }
+
+ public void installPackageEtc(
+ final Uri packageURI, final IPackageInstallObserver observer,
+ final IPackageInstallObserver2 observer2, final int flags,
+ final String installerPackageName) {
+ installPackageWithVerificationEtc(packageURI, observer, observer2, flags,
+ installerPackageName, null, null, null);
+ }
+
+ @Override
+ public void installPackageWithVerificationEtc(Uri packageURI, IPackageInstallObserver observer,
+ IPackageInstallObserver2 observer2,
+ int flags, String installerPackageName, Uri verificationURI,
+ ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
+ VerificationParams verificationParams = new VerificationParams(verificationURI, null, null,
+ VerificationParams.NO_UID, manifestDigest);
+ installPackageWithVerificationAndEncryptionEtc(packageURI, observer, observer2, flags,
+ installerPackageName, verificationParams, encryptionParams);
+ }
+
+ /*
+ * All of the installPackage...*() methods redirect to this one for the master implementation
+ */
+ public void installPackageWithVerificationAndEncryptionEtc(Uri packageURI,
+ IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
+ int flags, String installerPackageName,
+ VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+ if (observer == null && observer2 == null) {
+ throw new IllegalArgumentException("No install observer supplied");
+ }
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
null);
final int uid = Binder.getCallingUid();
if (isUserRestricted(UserHandle.getUserId(uid), UserManager.DISALLOW_INSTALL_APPS)) {
try {
- observer.packageInstalled("", PackageManager.INSTALL_FAILED_USER_RESTRICTED);
+ if (observer != null) {
+ observer.packageInstalled("", PackageManager.INSTALL_FAILED_USER_RESTRICTED);
+ }
+ if (observer2 != null) {
+ observer2.packageInstalled("", null, PackageManager.INSTALL_FAILED_USER_RESTRICTED);
+ }
} catch (RemoteException re) {
}
return;
@@ -6832,8 +6910,8 @@
verificationParams.setInstallerUid(uid);
final Message msg = mHandler.obtainMessage(INIT_COPY);
- msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
- verificationParams, encryptionParams, user);
+ msg.obj = new InstallParams(packageURI, observer, observer2, filteredFlags,
+ installerPackageName, verificationParams, encryptionParams, user);
mHandler.sendMessage(msg);
}
@@ -7455,32 +7533,34 @@
mSuccess = getPackageSizeInfoLI(mStats.packageName, mStats.userHandle, mStats);
}
- final boolean mounted;
- if (Environment.isExternalStorageEmulated()) {
- mounted = true;
- } else {
- final String status = Environment.getExternalStorageState();
- mounted = (Environment.MEDIA_MOUNTED.equals(status)
- || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));
- }
+ if (mSuccess) {
+ final boolean mounted;
+ if (Environment.isExternalStorageEmulated()) {
+ mounted = true;
+ } else {
+ final String status = Environment.getExternalStorageState();
+ mounted = (Environment.MEDIA_MOUNTED.equals(status)
+ || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status));
+ }
- if (mounted) {
- final UserEnvironment userEnv = new UserEnvironment(mStats.userHandle);
+ if (mounted) {
+ final UserEnvironment userEnv = new UserEnvironment(mStats.userHandle);
- mStats.externalCacheSize = calculateDirectorySize(mContainerService,
- userEnv.buildExternalStorageAppCacheDirs(mStats.packageName));
+ mStats.externalCacheSize = calculateDirectorySize(mContainerService,
+ userEnv.buildExternalStorageAppCacheDirs(mStats.packageName));
- mStats.externalDataSize = calculateDirectorySize(mContainerService,
- userEnv.buildExternalStorageAppDataDirs(mStats.packageName));
+ mStats.externalDataSize = calculateDirectorySize(mContainerService,
+ userEnv.buildExternalStorageAppDataDirs(mStats.packageName));
- // Always subtract cache size, since it's a subdirectory
- mStats.externalDataSize -= mStats.externalCacheSize;
+ // Always subtract cache size, since it's a subdirectory
+ mStats.externalDataSize -= mStats.externalCacheSize;
- mStats.externalMediaSize = calculateDirectorySize(mContainerService,
- userEnv.buildExternalStorageAppMediaDirs(mStats.packageName));
+ mStats.externalMediaSize = calculateDirectorySize(mContainerService,
+ userEnv.buildExternalStorageAppMediaDirs(mStats.packageName));
- mStats.externalObbSize = calculateDirectorySize(mContainerService,
- userEnv.buildExternalStorageAppObbDirs(mStats.packageName));
+ mStats.externalObbSize = calculateDirectorySize(mContainerService,
+ userEnv.buildExternalStorageAppObbDirs(mStats.packageName));
+ }
}
}
@@ -7522,6 +7602,7 @@
class InstallParams extends HandlerParams {
final IPackageInstallObserver observer;
+ final IPackageInstallObserver2 observer2;
int flags;
private final Uri mPackageURI;
@@ -7533,13 +7614,14 @@
final ContainerEncryptionParams encryptionParams;
InstallParams(Uri packageURI,
- IPackageInstallObserver observer, int flags,
- String installerPackageName, VerificationParams verificationParams,
+ IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
+ int flags, String installerPackageName, VerificationParams verificationParams,
ContainerEncryptionParams encryptionParams, UserHandle user) {
super(user);
this.mPackageURI = packageURI;
this.flags = flags;
this.observer = observer;
+ this.observer2 = observer2;
this.installerPackageName = installerPackageName;
this.verificationParams = verificationParams;
this.encryptionParams = encryptionParams;
@@ -8109,6 +8191,7 @@
static abstract class InstallArgs {
final IPackageInstallObserver observer;
+ final IPackageInstallObserver2 observer2;
// Always refers to PackageManager flags only
final int flags;
final Uri packageURI;
@@ -8116,12 +8199,14 @@
final ManifestDigest manifestDigest;
final UserHandle user;
- InstallArgs(Uri packageURI, IPackageInstallObserver observer, int flags,
- String installerPackageName, ManifestDigest manifestDigest,
+ InstallArgs(Uri packageURI,
+ IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
+ int flags, String installerPackageName, ManifestDigest manifestDigest,
UserHandle user) {
this.packageURI = packageURI;
this.flags = flags;
this.observer = observer;
+ this.observer2 = observer2;
this.installerPackageName = installerPackageName;
this.manifestDigest = manifestDigest;
this.user = user;
@@ -8178,13 +8263,13 @@
boolean created = false;
FileInstallArgs(InstallParams params) {
- super(params.getPackageUri(), params.observer, params.flags,
+ super(params.getPackageUri(), params.observer, params.observer2, params.flags,
params.installerPackageName, params.getManifestDigest(),
params.getUser());
}
FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
- super(null, null, 0, null, null, null);
+ super(null, null, null, 0, null, null, null);
File codeFile = new File(fullCodePath);
installDir = codeFile.getParentFile();
codeFileName = fullCodePath;
@@ -8193,7 +8278,7 @@
}
FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
- super(packageURI, null, 0, null, null, null);
+ super(packageURI, null, null, 0, null, null, null);
installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
String apkName = getNextCodePath(null, pkgName, ".apk");
codeFileName = new File(installDir, apkName + ".apk").getPath();
@@ -8514,14 +8599,14 @@
String libraryPath;
AsecInstallArgs(InstallParams params) {
- super(params.getPackageUri(), params.observer, params.flags,
+ super(params.getPackageUri(), params.observer, params.observer2, params.flags,
params.installerPackageName, params.getManifestDigest(),
params.getUser());
}
AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
boolean isExternal, boolean isForwardLocked) {
- super(null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
+ super(null, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
| (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
null, null, null);
// Extract cid from fullCodePath
@@ -8533,7 +8618,7 @@
}
AsecInstallArgs(String cid, boolean isForwardLocked) {
- super(null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0)
+ super(null, null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0)
| (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
null, null, null);
this.cid = cid;
@@ -8541,7 +8626,7 @@
}
AsecInstallArgs(Uri packageURI, String cid, boolean isExternal, boolean isForwardLocked) {
- super(packageURI, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
+ super(packageURI, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
| (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
null, null, null);
this.cid = cid;
@@ -8875,6 +8960,10 @@
PackageParser.Package pkg;
int returnCode;
PackageRemovedInfo removedInfo;
+
+ // In some error cases we want to convey more info back to the observer
+ String origPackage;
+ String origPermission;
}
/*
@@ -9125,9 +9214,20 @@
final PackageSetting newPkgSetting = (PackageSetting)newPackage.mExtras;
newPkgSetting.firstInstallTime = oldPkgSetting.firstInstallTime;
newPkgSetting.lastUpdateTime = System.currentTimeMillis();
+
+ // is the update attempting to change shared user? that isn't going to work...
+ if (oldPkgSetting.sharedUser != newPkgSetting.sharedUser) {
+ Slog.w(TAG, "Forbidding shared user change from " + oldPkgSetting.sharedUser
+ + " to " + newPkgSetting.sharedUser);
+ res.returnCode = PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
+ updatedSettings = true;
+ }
}
- updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
- updatedSettings = true;
+
+ if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
+ updateSettingsLI(newPackage, installerPackageName, allUsers, perUserInstalled, res);
+ updatedSettings = true;
+ }
}
if (res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
@@ -9299,6 +9399,27 @@
String oldCodePath = null;
boolean systemApp = false;
synchronized (mPackages) {
+ // Check whether the newly-scanned package wants to define an already-defined perm
+ int N = pkg.permissions.size();
+ for (int i = 0; i < N; i++) {
+ PackageParser.Permission perm = pkg.permissions.get(i);
+ BasePermission bp = mSettings.mPermissions.get(perm.info.name);
+ if (bp != null) {
+ // If the defining package is signed with our cert, it's okay. This
+ // also includes the "updating the same package" case, of course.
+ if (compareSignatures(bp.packageSetting.signatures.mSignatures,
+ pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
+ Slog.w(TAG, "Package " + pkg.packageName
+ + " attempting to redeclare permission " + perm.info.name
+ + " already owned by " + bp.sourcePackage);
+ res.returnCode = PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
+ res.origPermission = perm.info.name;
+ res.origPackage = bp.sourcePackage;
+ return;
+ }
+ }
+ }
+
// Check if installing already existing package
if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
String oldName = mSettings.mRenamedPackages.get(pkgName);
@@ -10163,6 +10284,9 @@
final IPackageStatsObserver observer) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.GET_PACKAGE_SIZE, null);
+ if (packageName == null) {
+ throw new IllegalArgumentException("Attempt to get size of null packageName");
+ }
PackageStats stats = new PackageStats(packageName, userHandle);
@@ -11325,6 +11449,10 @@
*/
public void scanAvailableAsecs() {
updateExternalMediaStatusInner(true, false, false);
+ if (mShouldRestoreconData) {
+ SELinuxMMAC.setRestoreconDone();
+ mShouldRestoreconData = false;
+ }
}
/*
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 9236bde..37547f2 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1477,6 +1477,7 @@
// FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
// system/core/run-as/run-as.c
// system/core/sdcard/sdcard.c
+ // external/libselinux/src/android.c:package_info_init()
//
sb.setLength(0);
sb.append(ai.packageName);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 7f55464..a39e958 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -92,7 +92,7 @@
private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
private static final String ATTR_PARTIAL = "partial";
private static final String ATTR_USER_VERSION = "version";
- private static final String ATTR_RELATED_GROUP_ID = "relatedGroupId";
+ private static final String ATTR_PROFILE_GROUP_ID = "profileGroupId";
private static final String TAG_USERS = "users";
private static final String TAG_USER = "user";
private static final String TAG_RESTRICTIONS = "restrictions";
@@ -257,26 +257,26 @@
}
@Override
- public List<UserInfo> getRelatedUsers(int userId) {
+ public List<UserInfo> getProfiles(int userId) {
checkManageUsersPermission("query users");
synchronized (mPackagesLock) {
UserInfo user = getUserInfoLocked(userId);
ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
for (int i = 0; i < mUsers.size(); i++) {
- UserInfo ui = mUsers.valueAt(i);
- if (!areRelatedUsers(user, ui)) {
+ UserInfo profile = mUsers.valueAt(i);
+ if (!isProfileOf(user, profile)) {
continue;
}
- users.add(ui);
+ users.add(profile);
}
return users;
}
}
- private boolean areRelatedUsers(UserInfo user1, UserInfo user2) {
- return user1.relatedGroupId != UserInfo.NO_RELATED_GROUP_ID &&
- user1.relatedGroupId == user2.relatedGroupId &&
- user1.id != user2.id;
+ private boolean isProfileOf(UserInfo user, UserInfo profile) {
+ return user.id == profile.id ||
+ (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
+ && user.profileGroupId == profile.profileGroupId);
}
@Override
@@ -684,9 +684,9 @@
if (userInfo.partial) {
serializer.attribute(null, ATTR_PARTIAL, "true");
}
- if (userInfo.relatedGroupId != UserInfo.NO_RELATED_GROUP_ID) {
- serializer.attribute(null, ATTR_RELATED_GROUP_ID,
- Integer.toString(userInfo.relatedGroupId));
+ if (userInfo.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) {
+ serializer.attribute(null, ATTR_PROFILE_GROUP_ID,
+ Integer.toString(userInfo.profileGroupId));
}
serializer.startTag(null, TAG_NAME);
@@ -771,7 +771,7 @@
long salt = 0L;
String pinHash = null;
int failedAttempts = 0;
- int relatedGroupId = UserInfo.NO_RELATED_GROUP_ID;
+ int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID;
long lastAttemptTime = 0L;
boolean partial = false;
Bundle restrictions = new Bundle();
@@ -809,8 +809,14 @@
pinHash = parser.getAttributeValue(null, ATTR_PIN_HASH);
failedAttempts = readIntAttribute(parser, ATTR_FAILED_ATTEMPTS, 0);
lastAttemptTime = readLongAttribute(parser, ATTR_LAST_RETRY_MS, 0L);
- relatedGroupId = readIntAttribute(parser, ATTR_RELATED_GROUP_ID,
- UserInfo.NO_RELATED_GROUP_ID);
+ profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID,
+ UserInfo.NO_PROFILE_GROUP_ID);
+ if (profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
+ // This attribute was added and renamed during development of L.
+ // TODO Remove upgrade path by 1st May 2014
+ profileGroupId = readIntAttribute(parser, "relatedGroupId",
+ UserInfo.NO_PROFILE_GROUP_ID);
+ }
String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
if ("true".equals(valueString)) {
partial = true;
@@ -849,7 +855,7 @@
userInfo.creationTime = creationTime;
userInfo.lastLoggedInTime = lastLoggedInTime;
userInfo.partial = partial;
- userInfo.relatedGroupId = relatedGroupId;
+ userInfo.profileGroupId = profileGroupId;
mUserRestrictions.append(id, restrictions);
if (salt != 0L) {
RestrictionsPinState pinState = mRestrictionsPinStates.get(id);
@@ -964,25 +970,25 @@
}
}
- private int getNextRelatedGroupIdLocked() {
- int maxGroupId = UserInfo.NO_RELATED_GROUP_ID;
+ 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.relatedGroupId) {
- maxGroupId = ui.relatedGroupId;
+ if (maxGroupId < ui.profileGroupId) {
+ maxGroupId = ui.profileGroupId;
}
}
return maxGroupId + 1;
}
@Override
- public UserInfo createRelatedUser(String name, int flags, int relatedUserId) {
+ public UserInfo createProfileForUser(String name, int flags, int userId) {
checkManageUsersPermission("Only the system can create users");
- if (relatedUserId != UserHandle.USER_OWNER) {
- Slog.w(LOG_TAG, "Only user owner can have related users");
+ if (userId != UserHandle.USER_OWNER) {
+ Slog.w(LOG_TAG, "Only user owner can have profiles");
return null;
}
- return createUserInternal(name, flags, relatedUserId);
+ return createUserInternal(name, flags, userId);
}
@Override
@@ -991,16 +997,16 @@
return createUserInternal(name, flags, UserHandle.USER_NULL);
}
- private UserInfo createUserInternal(String name, int flags, int relatedUserId) {
+ private UserInfo createUserInternal(String name, int flags, int profileId) {
final long ident = Binder.clearCallingIdentity();
UserInfo userInfo = null;
try {
synchronized (mInstallLock) {
synchronized (mPackagesLock) {
- UserInfo relatedUser = null;
- if (relatedUserId != UserHandle.USER_NULL) {
- relatedUser = getUserInfoLocked(relatedUserId);
- if (relatedUser == null) return null;
+ UserInfo profile = null;
+ if (profileId != UserHandle.USER_NULL) {
+ profile = getUserInfoLocked(profileId);
+ if (profile == null) return null;
}
if (isUserLimitReachedLocked()) return null;
int userId = getNextAvailableIdLocked();
@@ -1013,12 +1019,12 @@
Environment.getUserSystemDirectory(userInfo.id).mkdirs();
mUsers.put(userId, userInfo);
writeUserListLocked();
- if (relatedUser != null) {
- if (relatedUser.relatedGroupId == UserInfo.NO_RELATED_GROUP_ID) {
- relatedUser.relatedGroupId = getNextRelatedGroupIdLocked();
+ if (profile != null) {
+ if (profile.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
+ profile.profileGroupId = getNextProfileGroupIdLocked();
+ writeUserLocked(profile);
}
- userInfo.relatedGroupId = relatedUser.relatedGroupId;
- writeUserLocked(relatedUser);
+ userInfo.profileGroupId = profile.profileGroupId;
}
writeUserLocked(userInfo);
mPm.createNewUserLILPw(userId, userPath);
diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
index 260e97a..eb38f4a 100644
--- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
+++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
@@ -455,6 +455,7 @@
notification.flags |= Notification.FLAG_NO_CLEAR;
notification.setLatestEventInfo(context, title, details, intent);
notification.visibility = Notification.VISIBILITY_PUBLIC;
+ notification.category = Notification.CATEGORY_SYSTEM;
mNotificationMgr.notifyAsUser(null, LOW_MEMORY_NOTIFICATION_ID, notification,
UserHandle.ALL);
context.sendStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
new file mode 100644
index 0000000..a83fa87
--- /dev/null
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -0,0 +1,166 @@
+/*
+ * 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.server.trust;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.Slog;
+import android.service.trust.ITrustAgentService;
+import android.service.trust.ITrustAgentServiceCallback;
+
+/**
+ * A wrapper around a TrustAgentService interface. Coordinates communication between
+ * TrustManager and the actual TrustAgent.
+ */
+public class TrustAgentWrapper {
+ private static final boolean DEBUG = false;
+ private static final String TAG = "TrustAgentWrapper";
+
+ private static final int MSG_ENABLE_TRUST = 1;
+ private static final int MSG_REVOKE_TRUST = 2;
+ private static final int MSG_TRUST_TIMEOUT = 3;
+
+ private final TrustManagerService mTrustManagerService;
+ private final int mUserId;
+ private final Context mContext;
+ private final ComponentName mName;
+
+ private ITrustAgentService mTrustAgentService;
+
+ // Trust state
+ private boolean mTrusted;
+ private String mMessage;
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_ENABLE_TRUST:
+ mTrusted = true;
+ mMessage = (String) msg.obj;
+ boolean initiatedByUser = msg.arg1 != 0;
+ // TODO: Handle handle user initiated trust changes.
+ mTrustManagerService.updateTrust(mUserId);
+ break;
+ case MSG_TRUST_TIMEOUT:
+ if (DEBUG) Slog.v(TAG, "Trust timed out : " + mName.flattenToShortString());
+ // Fall through.
+ case MSG_REVOKE_TRUST:
+ mTrusted = false;
+ mMessage = null;
+ mTrustManagerService.updateTrust(mUserId);
+ break;
+ }
+ }
+ };
+
+ private ITrustAgentServiceCallback mCallback = new ITrustAgentServiceCallback.Stub() {
+
+ public void enableTrust(String userMessage, long durationMs, boolean initiatedByUser) {
+ if (DEBUG) Slog.v(TAG, "enableTrust(" + userMessage + ", durationMs = " + durationMs
+ + ", initiatedByUser = " + initiatedByUser + ")");
+
+ mHandler.obtainMessage(MSG_ENABLE_TRUST, initiatedByUser ? 1 : 0, 0, userMessage)
+ .sendToTarget();
+ if (durationMs > 0) {
+ mHandler.removeMessages(MSG_TRUST_TIMEOUT);
+ mHandler.sendEmptyMessageDelayed(MSG_TRUST_TIMEOUT, durationMs);
+ }
+ }
+
+ public void revokeTrust() {
+ if (DEBUG) Slog.v(TAG, "revokeTrust()");
+ mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
+ }
+ };
+
+ private final ServiceConnection mConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (DEBUG) Log.v(TAG, "TrustAgent started : " + name.flattenToString());
+ mTrustAgentService = ITrustAgentService.Stub.asInterface(service);
+ setCallback(mCallback);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (DEBUG) Log.v(TAG, "TrustAgent disconnected : " + name.flattenToShortString());
+ mTrustAgentService = null;
+ mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
+ }
+ };
+
+
+ public TrustAgentWrapper(Context context, TrustManagerService trustManagerService,
+ Intent intent, UserHandle user) {
+ mContext = context;
+ mTrustManagerService = trustManagerService;
+ mUserId = user.getIdentifier();
+ mName = intent.getComponent();
+ if (!context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, user)) {
+ if (DEBUG) Log.v(TAG, "can't bind to TrustAgent " + mName.flattenToShortString());
+ // TODO: retry somehow?
+ }
+ }
+
+ private void onError(Exception e) {
+ Slog.w(TAG , "Remote Exception", e);
+ }
+
+ /**
+ * @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean)
+ */
+ public void onUnlockAttempt(boolean successful) {
+ try {
+ if (mTrustAgentService != null) mTrustAgentService.onUnlockAttempt(successful);
+ } catch (RemoteException e) {
+ onError(e);
+ }
+ }
+
+ private void setCallback(ITrustAgentServiceCallback callback) {
+ try {
+ if (mTrustAgentService != null) {
+ mTrustAgentService.setCallback(callback);
+ }
+ } catch (RemoteException e) {
+ onError(e);
+ }
+ }
+
+ public boolean isTrusted() {
+ return mTrusted;
+ }
+
+ public String getMessage() {
+ return mMessage;
+ }
+
+ public void unbind() {
+ if (DEBUG) Log.v(TAG, "TrustAgent unbound : " + mName.flattenToShortString());
+ mContext.unbindService(mConnection);
+ }
+}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
new file mode 100644
index 0000000..a2a49c9
--- /dev/null
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -0,0 +1,387 @@
+/*
+ * 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.server.trust;
+
+import com.android.internal.content.PackageMonitor;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.server.SystemService;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.Manifest;
+import android.app.trust.ITrustListener;
+import android.app.trust.ITrustManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.service.trust.TrustAgentService;
+import android.util.ArraySet;
+import android.util.AttributeSet;
+import android.util.Slog;
+import android.util.Xml;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Manages trust agents and trust listeners.
+ *
+ * It is responsible for binding to the enabled {@link android.service.trust.TrustAgentService}s
+ * of each user and notifies them about events that are relevant to them.
+ * It start and stops them based on the value of
+ * {@link com.android.internal.widget.LockPatternUtils#getEnabledTrustAgents(int)}.
+ *
+ * It also keeps a set of {@link android.app.trust.ITrustListener}s that are notified whenever the
+ * trust state changes for any user.
+ *
+ * Trust state and the setting of enabled agents is kept per user and each user has its own
+ * instance of a {@link android.service.trust.TrustAgentService}.
+ */
+public class TrustManagerService extends SystemService {
+
+ private static final boolean DEBUG = false;
+ private static final String TAG = "TrustManagerService";
+
+ private static final Intent TRUST_AGENT_INTENT =
+ new Intent(TrustAgentService.SERVICE_INTERFACE);
+
+ private static final int MSG_REGISTER_LISTENER = 1;
+ private static final int MSG_UNREGISTER_LISTENER = 2;
+ private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
+ private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
+
+ private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
+ private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
+ private final Context mContext;
+
+ private UserManager mUserManager;
+
+ /**
+ * Cache for {@link #refreshAgentList()}
+ */
+ private final ArraySet<AgentInfo> mObsoleteAgents = new ArraySet<AgentInfo>();
+
+
+ public TrustManagerService(Context context) {
+ super(context);
+ mContext = context;
+ mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.TRUST_SERVICE, mService);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) {
+ // Listen for package changes
+ mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
+ refreshAgentList();
+ }
+ }
+
+ // Agent management
+
+ private static final class AgentInfo {
+ CharSequence label;
+ Drawable icon;
+ ComponentName component; // service that implements ITrustAgent
+ ComponentName settings; // setting to launch to modify agent.
+ TrustAgentWrapper agent;
+ int userId;
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof AgentInfo)) {
+ return false;
+ }
+ AgentInfo o = (AgentInfo) other;
+ return component.equals(o.component) && userId == o.userId;
+ }
+
+ @Override
+ public int hashCode() {
+ return component.hashCode() * 31 + userId;
+ }
+ }
+
+ private void updateTrustAll() {
+ List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
+ for (UserInfo userInfo : userInfos) {
+ updateTrust(userInfo.id);
+ }
+ }
+
+ public void updateTrust(int userId) {
+ dispatchOnTrustChanged(aggregateIsTrusted(userId), userId);
+ }
+
+ protected void refreshAgentList() {
+ if (DEBUG) Slog.d(TAG, "refreshAgentList()");
+ PackageManager pm = mContext.getPackageManager();
+
+ List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
+ LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
+
+ mObsoleteAgents.clear();
+ mObsoleteAgents.addAll(mActiveAgents);
+
+ for (UserInfo userInfo : userInfos) {
+ List<ComponentName> enabledAgents = lockPatternUtils.getEnabledTrustAgents(userInfo.id);
+ if (enabledAgents == null) {
+ continue;
+ }
+ List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT,
+ PackageManager.GET_META_DATA, userInfo.id);
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ if (resolveInfo.serviceInfo == null) continue;
+ ComponentName name = getComponentName(resolveInfo);
+ if (!enabledAgents.contains(name)) continue;
+
+ AgentInfo agentInfo = new AgentInfo();
+ agentInfo.component = name;
+ agentInfo.userId = userInfo.id;
+ if (!mActiveAgents.contains(agentInfo)) {
+ agentInfo.label = resolveInfo.loadLabel(pm);
+ agentInfo.icon = resolveInfo.loadIcon(pm);
+ agentInfo.settings = getSettingsComponentName(pm, resolveInfo);
+ agentInfo.agent = new TrustAgentWrapper(mContext, this,
+ new Intent().setComponent(name), userInfo.getUserHandle());
+ mActiveAgents.add(agentInfo);
+ } else {
+ mObsoleteAgents.remove(agentInfo);
+ }
+ }
+ }
+
+ boolean trustMayHaveChanged = false;
+ for (int i = 0; i < mObsoleteAgents.size(); i++) {
+ AgentInfo info = mActiveAgents.valueAt(i);
+ if (info.agent.isTrusted()) {
+ trustMayHaveChanged = true;
+ }
+ info.agent.unbind();
+ mActiveAgents.remove(info);
+ }
+
+ if (trustMayHaveChanged) {
+ updateTrustAll();
+ }
+ }
+
+ private ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
+ if (resolveInfo == null || resolveInfo.serviceInfo == null
+ || resolveInfo.serviceInfo.metaData == null) return null;
+ String cn = null;
+ XmlResourceParser parser = null;
+ Exception caughtException = null;
+ try {
+ parser = resolveInfo.serviceInfo.loadXmlMetaData(pm,
+ TrustAgentService.TRUST_AGENT_META_DATA);
+ if (parser == null) {
+ Slog.w(TAG, "Can't find " + TrustAgentService.TRUST_AGENT_META_DATA + " meta-data");
+ return null;
+ }
+ Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo);
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && type != XmlPullParser.START_TAG) {
+ // Drain preamble.
+ }
+ String nodeName = parser.getName();
+ if (!"trust_agent".equals(nodeName)) {
+ Slog.w(TAG, "Meta-data does not start with trust_agent tag");
+ return null;
+ }
+ TypedArray sa = res
+ .obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent);
+ cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity);
+ sa.recycle();
+ } catch (PackageManager.NameNotFoundException e) {
+ caughtException = e;
+ } catch (IOException e) {
+ caughtException = e;
+ } catch (XmlPullParserException e) {
+ caughtException = e;
+ } finally {
+ if (parser != null) parser.close();
+ }
+ if (caughtException != null) {
+ Slog.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException);
+ return null;
+ }
+ if (cn == null) {
+ return null;
+ }
+ if (cn.indexOf('/') < 0) {
+ cn = resolveInfo.serviceInfo.packageName + "/" + cn;
+ }
+ return ComponentName.unflattenFromString(cn);
+ }
+
+ private ComponentName getComponentName(ResolveInfo resolveInfo) {
+ if (resolveInfo == null || resolveInfo.serviceInfo == null) return null;
+ return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
+ }
+
+ // Agent dispatch and aggregation
+
+ private boolean aggregateIsTrusted(int userId) {
+ for (int i = 0; i < mActiveAgents.size(); i++) {
+ AgentInfo info = mActiveAgents.valueAt(i);
+ if (info.userId == userId) {
+ if (info.agent.isTrusted()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private void dispatchUnlockAttempt(boolean successful, int userId) {
+ for (int i = 0; i < mActiveAgents.size(); i++) {
+ AgentInfo info = mActiveAgents.valueAt(i);
+ if (info.userId == userId) {
+ info.agent.onUnlockAttempt(successful);
+ }
+ }
+ }
+
+ // Listeners
+
+ private void addListener(ITrustListener listener) {
+ for (int i = 0; i < mTrustListeners.size(); i++) {
+ if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
+ return;
+ }
+ }
+ mTrustListeners.add(listener);
+ }
+
+ private void removeListener(ITrustListener listener) {
+ for (int i = 0; i < mTrustListeners.size(); i++) {
+ if (mTrustListeners.get(i).asBinder() == listener.asBinder()) {
+ mTrustListeners.get(i);
+ return;
+ }
+ }
+ }
+
+ private void dispatchOnTrustChanged(boolean enabled, int userId) {
+ for (int i = 0; i < mTrustListeners.size(); i++) {
+ try {
+ mTrustListeners.get(i).onTrustChanged(enabled, userId);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Exception while notifying TrustListener. Removing listener.", e);
+ mTrustListeners.get(i);
+ i--;
+ }
+ }
+ }
+
+ // Plumbing
+
+ private final IBinder mService = new ITrustManager.Stub() {
+ @Override
+ public void reportUnlockAttempt(boolean authenticated, int userId) throws RemoteException {
+ enforceReportPermission();
+ mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_ATTEMPT, authenticated ? 1 : 0, userId)
+ .sendToTarget();
+ }
+
+ @Override
+ public void reportEnabledTrustAgentsChanged(int userId) throws RemoteException {
+ enforceReportPermission();
+ // coalesce refresh messages.
+ mHandler.removeMessages(MSG_ENABLED_AGENTS_CHANGED);
+ mHandler.sendEmptyMessage(MSG_ENABLED_AGENTS_CHANGED);
+ }
+
+ @Override
+ public void registerTrustListener(ITrustListener trustListener) throws RemoteException {
+ enforceListenerPermission();
+ mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget();
+ }
+
+ @Override
+ public void unregisterTrustListener(ITrustListener trustListener) throws RemoteException {
+ enforceListenerPermission();
+ mHandler.obtainMessage(MSG_UNREGISTER_LISTENER, trustListener).sendToTarget();
+ }
+
+ private void enforceReportPermission() {
+ mContext.enforceCallingPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE,
+ "reporting trust events");
+ }
+
+ private void enforceListenerPermission() {
+ mContext.enforceCallingPermission(Manifest.permission.TRUST_LISTENER,
+ "register trust listener");
+ }
+ };
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_REGISTER_LISTENER:
+ addListener((ITrustListener) msg.obj);
+ break;
+ case MSG_UNREGISTER_LISTENER:
+ removeListener((ITrustListener) msg.obj);
+ break;
+ case MSG_DISPATCH_UNLOCK_ATTEMPT:
+ dispatchUnlockAttempt(msg.arg1 != 0, msg.arg2);
+ break;
+ case MSG_ENABLED_AGENTS_CHANGED:
+ refreshAgentList();
+ break;
+ }
+ }
+ };
+
+ private final PackageMonitor mPackageMonitor = new PackageMonitor() {
+ @Override
+ public void onSomePackagesChanged() {
+ refreshAgentList();
+ }
+
+ @Override
+ public boolean onPackageChanged(String packageName, int uid, String[] components) {
+ // We're interested in all changes, even if just some components get enabled / disabled.
+ return true;
+ }
+ };
+}
diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java
new file mode 100644
index 0000000..fbfca93
--- /dev/null
+++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java
@@ -0,0 +1,110 @@
+/*
+ * 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.server.wm;
+
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.util.Log;
+import android.view.Display;
+import android.view.Surface;
+import android.view.Surface.OutOfResourcesException;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+class CircularDisplayMask {
+ private static final String TAG = "CircularDisplayMask";
+
+ private static final int STROKE_WIDTH = 2;
+
+ private final SurfaceControl mSurfaceControl;
+ private final Surface mSurface = new Surface();
+ private int mLastDW;
+ private int mLastDH;
+ private boolean mDrawNeeded;
+ private Paint mPaint;
+
+ public CircularDisplayMask(Display display, SurfaceSession session, int zOrder) {
+ SurfaceControl ctrl = null;
+ try {
+ ctrl = new SurfaceControl(session, "CircularDisplayMask",
+ 320, 290, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+ ctrl.setLayerStack(display.getLayerStack());
+ ctrl.setLayer(zOrder);
+ ctrl.setPosition(0, 0);
+ ctrl.show();
+ mSurface.copyFrom(ctrl);
+ } catch (OutOfResourcesException e) {
+ }
+ mSurfaceControl = ctrl;
+ mDrawNeeded = true;
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setColor(Color.BLACK);
+ mPaint.setStrokeWidth(STROKE_WIDTH);
+ }
+
+ private void drawIfNeeded() {
+ if (!mDrawNeeded) {
+ return;
+ }
+ mDrawNeeded = false;
+
+ Rect dirty = new Rect(0, 0, mLastDW, mLastDH);
+ Canvas c = null;
+ try {
+ c = mSurface.lockCanvas(dirty);
+ } catch (IllegalArgumentException e) {
+ } catch (Surface.OutOfResourcesException e) {
+ }
+ if (c == null) {
+ return;
+ }
+ c.drawCircle(160, 160, 160, mPaint);
+
+ mSurface.unlockCanvasAndPost(c);
+ }
+
+ // Note: caller responsible for being inside
+ // Surface.openTransaction() / closeTransaction()
+ public void setVisibility(boolean on) {
+ if (mSurfaceControl == null) {
+ return;
+ }
+ drawIfNeeded();
+ if (on) {
+ mSurfaceControl.show();
+ } else {
+ mSurfaceControl.hide();
+ }
+ }
+
+ void positionSurface(int dw, int dh) {
+ if (mLastDW == dw && mLastDH == dh) {
+ return;
+ }
+ mLastDW = dw;
+ mLastDH = dh;
+ mSurfaceControl.setSize(dw, dh);
+ mDrawNeeded = true;
+ }
+
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0558b5a..b12ae4f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -86,6 +86,7 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
+import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
import android.util.DisplayMetrics;
@@ -285,6 +286,8 @@
private static final String DENSITY_OVERRIDE = "ro.config.density_override";
private static final String SIZE_OVERRIDE = "ro.config.size_override";
+ private static final String SCREEN_CIRCULAR = "ro.display.circular";
+
private static final int MAX_SCREENSHOT_RETRIES = 3;
final private KeyguardDisableHandler mKeyguardDisableHandler;
@@ -302,14 +305,14 @@
/**
* Current user when multi-user is enabled. Don't show windows of
- * non-current user. Also see mRelatedUserIds.
+ * non-current user. Also see mCurrentProfileIds.
*/
int mCurrentUserId;
/**
- * Users related to the current user. These are also allowed to show windows
+ * Users that are profiles of the current user. These are also allowed to show windows
* on the current user.
*/
- int[] mRelatedUserIds = new int[0];
+ int[] mCurrentProfileIds = new int[] {UserHandle.USER_OWNER};
final Context mContext;
@@ -422,6 +425,7 @@
final SurfaceSession mFxSession;
Watermark mWatermark;
StrictModeFlash mStrictModeFlash;
+ CircularDisplayMask mCircularDisplayMask;
FocusedStackFrame mFocusedStackFrame;
int mFocusedStackLayer;
@@ -819,6 +823,7 @@
}
LocalServices.addService(WindowManagerInternal.class, new LocalService());
+ showCircularDisplayMaskIfNeeded();
}
public InputMonitor getInputMonitor() {
@@ -920,6 +925,10 @@
final IWindow client = win.mClient;
final WindowToken token = win.mToken;
final DisplayContent displayContent = win.getDisplayContent();
+ if (displayContent == null) {
+ // It doesn't matter this display is going away.
+ return 0;
+ }
final WindowList windows = win.getWindowList();
final int N = windows.size();
@@ -1097,6 +1106,9 @@
private void addAttachedWindowToListLocked(final WindowState win, boolean addToToken) {
final WindowToken token = win.mToken;
final DisplayContent displayContent = win.getDisplayContent();
+ if (displayContent == null) {
+ return;
+ }
final WindowState attached = win.mAttachedWindow;
WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
@@ -2254,6 +2266,11 @@
return WindowManagerGlobal.ADD_APP_EXITING;
}
+ if (win.getDisplayContent() == null) {
+ Slog.w(TAG, "Adding window to Display that has been removed.");
+ return WindowManagerGlobal.ADD_INVALID_DISPLAY;
+ }
+
mPolicy.adjustWindowParamsLw(win.mAttrs);
win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
@@ -2743,7 +2760,7 @@
return;
}
- final DisplayInfo displayInfo = window.getDisplayContent().getDisplayInfo();
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
final RectF dispRect = new RectF(0, 0,
displayInfo.logicalWidth, displayInfo.logicalHeight);
matrix.mapRect(dispRect);
@@ -5213,16 +5230,16 @@
ShutdownThread.rebootSafeMode(mContext, confirm);
}
- public void updateRelatedUserIds(final int[] relatedUserIds) {
+ public void setCurrentProfileIds(final int[] currentProfileIds) {
synchronized (mWindowMap) {
- mRelatedUserIds = relatedUserIds;
+ mCurrentProfileIds = currentProfileIds;
}
}
- public void setCurrentUser(final int newUserId, final int[] relatedUserIds) {
+ public void setCurrentUser(final int newUserId, final int[] currentProfileIds) {
synchronized (mWindowMap) {
mCurrentUserId = newUserId;
- mRelatedUserIds = relatedUserIds;
+ mCurrentProfileIds = currentProfileIds;
mAppTransition.setCurrentUser(newUserId);
mPolicy.setCurrentUserLw(newUserId);
@@ -5238,10 +5255,10 @@
}
/* Called by WindowState */
- boolean isRelatedToOrCurrentUserLocked(int userId) {
+ boolean isCurrentProfileLocked(int userId) {
if (userId == mCurrentUserId) return true;
- for (int i = 0; i < mRelatedUserIds.length; i++) {
- if (mRelatedUserIds[i] == userId) return true;
+ for (int i = 0; i < mCurrentProfileIds.length; i++) {
+ if (mCurrentProfileIds[i] == userId) return true;
}
return false;
}
@@ -5471,6 +5488,37 @@
}
}
+ public void showCircularDisplayMaskIfNeeded() {
+ if (SystemProperties.getBoolean(SCREEN_CIRCULAR, false)) {
+ mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK));
+ }
+ }
+
+ public void showCircularMask() {
+ synchronized(mWindowMap) {
+
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+ ">>> OPEN TRANSACTION showDisplayMask");
+ SurfaceControl.openTransaction();
+ try {
+ // TODO(multi-display): support multiple displays
+ if (mCircularDisplayMask == null) {
+ mCircularDisplayMask = new CircularDisplayMask(
+ getDefaultDisplayContentLocked().getDisplay(),
+ mFxSession,
+ mPolicy.windowTypeToLayerLw(
+ WindowManager.LayoutParams.TYPE_POINTER)
+ * TYPE_LAYER_MULTIPLIER + 10);
+ }
+ mCircularDisplayMask.setVisibility(true);
+ } finally {
+ SurfaceControl.closeTransaction();
+ if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
+ "<<< CLOSE TRANSACTION showDisplayMask");
+ }
+ }
+ }
+
// TODO: more accounting of which pid(s) turned it on, keep count,
// only allow disables from pids which have count on, etc.
@Override
@@ -7095,6 +7143,8 @@
public static final int REMOVE_STARTING_TIMEOUT = 33;
+ public static final int SHOW_DISPLAY_MASK = 34;
+
@Override
public void handleMessage(Message msg) {
if (DEBUG_WINDOW_TRACE) {
@@ -7490,6 +7540,11 @@
break;
}
+ case SHOW_DISPLAY_MASK: {
+ showCircularMask();
+ break;
+ }
+
case DO_ANIMATION_CALLBACK: {
try {
((IRemoteCallback)msg.obj).sendResult(null);
@@ -8963,6 +9018,9 @@
if (mStrictModeFlash != null) {
mStrictModeFlash.positionSurface(defaultDw, defaultDh);
}
+ if (mCircularDisplayMask != null) {
+ mCircularDisplayMask.positionSurface(defaultDw, defaultDh);
+ }
boolean focusDisplayed = false;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 2c0e99e..dff75ef 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1249,7 +1249,7 @@
}
return win.mShowToOwnerOnly
- && !mService.isRelatedToOrCurrentUserLocked(UserHandle.getUserId(win.mOwnerUid));
+ && !mService.isCurrentProfileLocked(UserHandle.getUserId(win.mOwnerUid));
}
private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 6b3c368..3c9d53e 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -176,9 +176,15 @@
mAnimator = service.mAnimator;
mPolicy = service.mPolicy;
mContext = service.mContext;
- final DisplayInfo displayInfo = win.getDisplayContent().getDisplayInfo();
- mAnimDw = displayInfo.appWidth;
- mAnimDh = displayInfo.appHeight;
+ final DisplayContent displayContent = win.getDisplayContent();
+ if (displayContent != null) {
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+ mAnimDw = displayInfo.appWidth;
+ mAnimDh = displayInfo.appHeight;
+ } else {
+ Slog.w(TAG, "WindowStateAnimator ctor: Display has been removed");
+ // This is checked on return and dealt with.
+ }
mWin = win;
mAttachedWinAnimator = win.mAttachedWindow == null
diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
index c26a516..a58b00bce 100644
--- a/services/core/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/core/jni/com_android_server_AlarmManagerService.cpp
@@ -365,7 +365,9 @@
int result = impl->set(type, &ts);
if (result < 0)
{
- ALOGE("Unable to set alarm to %lld.%09lld: %s\n", seconds, nanoseconds, strerror(errno));
+ ALOGE("Unable to set alarm to %lld.%09lld: %s\n",
+ static_cast<long long>(seconds),
+ static_cast<long long>(nanoseconds), strerror(errno));
}
}
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp
index 6170c09..a00aaa8 100644
--- a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp
+++ b/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp
@@ -20,7 +20,7 @@
#include "ScopedPrimitiveArray.h"
-#include <cstring>
+#include <string>
#include <deque>
#include <map>
@@ -34,7 +34,6 @@
jmethodID handleMessage;
jmethodID handleHotplug;
jmethodID getActiveSource;
- jmethodID getOsdName;
jmethodID getLanguage;
} gHdmiCecServiceClassInfo;
@@ -63,30 +62,28 @@
void initialize();
// initialize individual logical device.
- int initLogicalDevice(int type);
- void releaseLogicalDevice(int type);
+ cec_logical_address_t initLogicalDevice(cec_device_type_t type);
+ void releaseLogicalDevice(cec_device_type_t type);
- cec_logical_address_t getLogicalAddress(int deviceType);
+ cec_logical_address_t getLogicalAddress(cec_device_type_t deviceType);
+ uint16_t getPhysicalAddress();
int getDeviceType(cec_logical_address_t addr);
void queueMessage(const MessageEntry& message);
void queueOutgoingMessage(const cec_message_t& message);
void sendReportPhysicalAddress();
void sendActiveSource(cec_logical_address_t srcAddr);
- void sendInactiveSource(cec_logical_address_t srcAddr);
- void sendImageViewOn(cec_logical_address_t srcAddr);
- void sendTextViewOn(cec_logical_address_t srcAddr);
- void sendGiveDevicePowerStatus(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr);
void sendFeatureAbort(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr,
int opcode, int reason);
void sendCecVersion(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr,
int version);
- void sendDeviceVendorID(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr);
+ void sendDeviceVendorId(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr);
void sendGiveDeviceVendorID(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr);
void sendSetOsdName(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr,
const char* name, size_t len);
void sendSetMenuLanguage(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr);
void sendCecMessage(const cec_message_t& message);
+ void setOsdName(const char* name, size_t len);
private:
enum {
@@ -104,6 +101,7 @@
static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
void updatePhysicalAddress();
+ void updateLogicalAddress();
void dispatchMessage(const MessageEntry& message);
void processIncomingMessage(const cec_message_t& msg);
@@ -147,7 +145,7 @@
};
// device type -> logical address mapping
- std::map<int, cec_logical_address_t> mLogicalDevices;
+ std::map<cec_device_type_t, cec_logical_address_t> mLogicalDevices;
hdmi_cec_device_t* mDevice;
jobject mCallbacksObj;
@@ -158,6 +156,7 @@
std::deque<MessageEntry> mMessageQueue;
uint16_t mPhysicalAddress;
+ std::string mOsdName;
};
@@ -173,6 +172,10 @@
updatePhysicalAddress();
}
+uint16_t HdmiCecHandler::getPhysicalAddress() {
+ return mPhysicalAddress;
+}
+
void HdmiCecHandler::updatePhysicalAddress() {
uint16_t addr;
if (!mDevice->get_physical_address(mDevice, &addr)) {
@@ -182,7 +185,17 @@
}
}
-int HdmiCecHandler::initLogicalDevice(int type) {
+void HdmiCecHandler::updateLogicalAddress() {
+ std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
+ for (; it != mLogicalDevices.end(); ++it) {
+ cec_logical_address_t addr;
+ if (!mDevice->get_logical_address(mDevice, it->first, &addr)) {
+ it->second = addr;
+ }
+ }
+}
+
+cec_logical_address_t HdmiCecHandler::initLogicalDevice(cec_device_type_t type) {
cec_logical_address_t addr;
int res = mDevice->allocate_logical_address(mDevice, type, &addr);
@@ -190,21 +203,21 @@
ALOGE("Logical Address Allocation failed: %d", res);
} else {
ALOGV("Logical Address Allocation success: %d", addr);
- mLogicalDevices.insert(std::pair<int, cec_logical_address_t>(type, addr));
+ mLogicalDevices.insert(std::pair<cec_device_type_t, cec_logical_address_t>(type, addr));
}
return addr;
}
-void HdmiCecHandler::releaseLogicalDevice(int type) {
- std::map<int, cec_logical_address_t>::iterator it = mLogicalDevices.find(type);
+void HdmiCecHandler::releaseLogicalDevice(cec_device_type_t type) {
+ std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.find(type);
if (it != mLogicalDevices.end()) {
mLogicalDevices.erase(it);
}
// TODO: remove the address monitored in HAL as well.
}
-cec_logical_address_t HdmiCecHandler::getLogicalAddress(int mDevicetype) {
- std::map<int, cec_logical_address_t>::iterator it = mLogicalDevices.find(mDevicetype);
+cec_logical_address_t HdmiCecHandler::getLogicalAddress(cec_device_type_t type) {
+ std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.find(type);
if (it != mLogicalDevices.end()) {
return it->second;
}
@@ -212,7 +225,7 @@
}
int HdmiCecHandler::getDeviceType(cec_logical_address_t addr) {
- std::map<int, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
+ std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
for (; it != mLogicalDevices.end(); ++it) {
if (it->second == addr) {
return it->first;
@@ -245,14 +258,15 @@
}
// Report physical address for each logical one hosted in it.
- std::map<int, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
+ std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
while (it != mLogicalDevices.end()) {
cec_message_t msg;
msg.initiator = it->second; // logical address
msg.destination = CEC_ADDR_BROADCAST;
msg.length = 4;
msg.body[0] = CEC_MESSAGE_REPORT_PHYSICAL_ADDRESS;
- std::memcpy(msg.body + 1, &mPhysicalAddress, 2);
+ msg.body[1] = (mPhysicalAddress >> 8) & 0xff;
+ msg.body[2] = mPhysicalAddress & 0xff;
msg.body[3] = it->first; // device type
queueOutgoingMessage(msg);
++it;
@@ -269,47 +283,8 @@
msg.destination = CEC_ADDR_BROADCAST;
msg.length = 3;
msg.body[0] = CEC_MESSAGE_ACTIVE_SOURCE;
- std::memcpy(msg.body + 1, &mPhysicalAddress, 2);
- queueOutgoingMessage(msg);
-}
-
-void HdmiCecHandler::sendInactiveSource(cec_logical_address_t srcAddr) {
- cec_message_t msg;
- msg.initiator = srcAddr;
- msg.destination = CEC_ADDR_TV;
- msg.length = 3;
- msg.body[0] = CEC_MESSAGE_INACTIVE_SOURCE;
- if (mPhysicalAddress != INVALID_PHYSICAL_ADDRESS) {
- std::memcpy(msg.body + 1, &mPhysicalAddress, 2);
- queueOutgoingMessage(msg);
- }
-}
-
-void HdmiCecHandler::sendImageViewOn(cec_logical_address_t srcAddr) {
- cec_message_t msg;
- msg.initiator = srcAddr;
- msg.destination = CEC_ADDR_TV;
- msg.length = 1;
- msg.body[0] = CEC_MESSAGE_IMAGE_VIEW_ON;
- queueOutgoingMessage(msg);
-}
-
-void HdmiCecHandler::sendTextViewOn(cec_logical_address_t srcAddr) {
- cec_message_t msg;
- msg.initiator = srcAddr;
- msg.destination = CEC_ADDR_TV;
- msg.length = 1;
- msg.body[0] = CEC_MESSAGE_TEXT_VIEW_ON;
- queueOutgoingMessage(msg);
-}
-
-void HdmiCecHandler::sendGiveDevicePowerStatus(cec_logical_address_t srcAddr,
- cec_logical_address_t dstAddr) {
- cec_message_t msg;
- msg.initiator = srcAddr;
- msg.destination = dstAddr;
- msg.length = 1;
- msg.body[0] = CEC_MESSAGE_GIVE_DEVICE_POWER_STATUS;
+ msg.body[1] = (mPhysicalAddress >> 8) & 0xff;
+ msg.body[2] = mPhysicalAddress & 0xff;
queueOutgoingMessage(msg);
}
@@ -346,7 +321,7 @@
queueOutgoingMessage(msg);
}
-void HdmiCecHandler::sendDeviceVendorID(cec_logical_address_t srcAddr,
+void HdmiCecHandler::sendDeviceVendorId(cec_logical_address_t srcAddr,
cec_logical_address_t dstAddr) {
cec_message_t msg;
msg.initiator = srcAddr;
@@ -355,7 +330,9 @@
msg.body[0] = CEC_MESSAGE_DEVICE_VENDOR_ID;
uint32_t vendor_id;
mDevice->get_vendor_id(mDevice, &vendor_id);
- std::memcpy(msg.body + 1, &vendor_id, 3);
+ msg.body[1] = (vendor_id >> 16) & 0xff;
+ msg.body[2] = (vendor_id >> 8) & 0xff;
+ msg.body[3] = vendor_id & 0xff;
queueOutgoingMessage(msg);
}
@@ -397,6 +374,10 @@
mDevice->send_message(mDevice, &message);
}
+void HdmiCecHandler::setOsdName(const char* name, size_t len) {
+ mOsdName.assign(name, min(len, CEC_MESSAGE_BODY_MAX_LENGTH - 1));
+}
+
// static
void HdmiCecHandler::onReceived(const hdmi_event_t* event, void* arg) {
HdmiCecHandler* handler = static_cast<HdmiCecHandler*>(arg);
@@ -437,9 +418,8 @@
mMessageQueue.pop_front();
bool connected = entry.second.hotplug.connected;
if (connected) {
- // TODO: Update logical addresses as well, since they also could have
- // changed while the cable was disconnected.
updatePhysicalAddress();
+ updateLogicalAddress();
}
propagateHotplug(connected);
}
@@ -460,6 +440,9 @@
handleGetCECVersion(msg);
} else if (opcode == CEC_MESSAGE_GET_MENU_LANGUAGE) {
handleGetMenuLanguage(msg);
+ } else if (opcode == CEC_MESSAGE_ABORT) {
+ // Compliance testing requires that abort message be responded with feature abort.
+ sendFeatureAbort(msg.destination, msg.initiator, msg.body[0], ABORT_REFUSED);
} else {
if (precheckMessage(msg)) {
propagateMessage(msg);
@@ -480,8 +463,7 @@
(opcode == CEC_MESSAGE_ACTIVE_SOURCE ||
opcode == CEC_MESSAGE_SET_STREAM_PATH ||
opcode == CEC_MESSAGE_INACTIVE_SOURCE)) {
- uint16_t senderAddr;
- std::memcpy(&senderAddr, &msg.body[1], 2);
+ uint16_t senderAddr = (msg.body[1] << 8) + msg.body[2];
if (senderAddr == mPhysicalAddress) {
return false;
}
@@ -521,28 +503,19 @@
jint activeDeviceType = env->CallIntMethod(mCallbacksObj,
gHdmiCecServiceClassInfo.getActiveSource);
if (activeDeviceType != INACTIVE_DEVICE_TYPE) {
- sendActiveSource(getLogicalAddress(activeDeviceType));
+ sendActiveSource(getLogicalAddress(static_cast<cec_device_type_t>(activeDeviceType)));
}
checkAndClearExceptionFromCallback(env, __FUNCTION__);
}
void HdmiCecHandler::handleGetOsdName(const cec_message_t& msg) {
- cec_logical_address_t addr = msg.destination;
- JNIEnv* env = AndroidRuntime::getJNIEnv();
- jbyteArray res = (jbyteArray) env->CallObjectMethod(mCallbacksObj,
- gHdmiCecServiceClassInfo.getOsdName,
- getDeviceType(addr));
- jbyte *name = env->GetByteArrayElements(res, NULL);
- if (name != NULL) {
- sendSetOsdName(addr, msg.initiator, reinterpret_cast<const char *>(name),
- env->GetArrayLength(res));
- env->ReleaseByteArrayElements(res, name, JNI_ABORT);
+ if (!mOsdName.empty()) {
+ sendSetOsdName(msg.destination, msg.initiator, mOsdName.c_str(), mOsdName.length());
}
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
}
void HdmiCecHandler::handleGiveDeviceVendorID(const cec_message_t& msg) {
- sendDeviceVendorID(msg.destination, msg.initiator);
+ sendDeviceVendorId(msg.destination, msg.initiator);
}
void HdmiCecHandler::handleGetCECVersion(const cec_message_t& msg) {
@@ -585,8 +558,6 @@
"handleHotplug", "(Z)V");
GET_METHOD_ID(gHdmiCecServiceClassInfo.getActiveSource, clazz,
"getActiveSource", "()I");
- GET_METHOD_ID(gHdmiCecServiceClassInfo.getOsdName, clazz,
- "getOsdName", "(I)[B");
GET_METHOD_ID(gHdmiCecServiceClassInfo.getLanguage, clazz,
"getLanguage", "(I)Ljava/lang/String;");
@@ -596,64 +567,43 @@
static void nativeSendMessage(JNIEnv* env, jclass clazz, jlong handlerPtr, jint deviceType,
jint dstAddr, jint opcode, jbyteArray params) {
HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
- cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
+ cec_logical_address_t srcAddr = handler->getLogicalAddress(
+ static_cast<cec_device_type_t>(deviceType));
jsize len = env->GetArrayLength(params);
ScopedByteArrayRO paramsPtr(env, params);
cec_message_t message;
message.initiator = srcAddr;
message.destination = static_cast<cec_logical_address_t>(dstAddr);
- message.length = len + 1;
+ message.length = min(len + 1, CEC_MESSAGE_BODY_MAX_LENGTH);
message.body[0] = opcode;
- std::memcpy(message.body + 1, paramsPtr.get(), len);
+ std::memcpy(message.body + 1, paramsPtr.get(), message.length - 1);
handler->sendCecMessage(message);
}
-static int nativeAllocateLogicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr,
+static jint nativeAllocateLogicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr,
jint deviceType) {
HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
- return handler->initLogicalDevice(deviceType);
+ return handler->initLogicalDevice(static_cast<cec_device_type_t>(deviceType));
}
static void nativeRemoveLogicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr,
jint deviceType) {
HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
- return handler->releaseLogicalDevice(deviceType);
+ return handler->releaseLogicalDevice(static_cast<cec_device_type_t>(deviceType));
}
-static void nativeSendActiveSource(JNIEnv* env, jclass clazz, jlong handlerPtr,
- jint deviceType) {
+static jint nativeGetPhysicalAddress(JNIEnv* env, jclass clazz, jlong handlerPtr) {
HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
- cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
- handler->sendActiveSource(srcAddr);
+ return handler->getPhysicalAddress();
}
-static void nativeSendInactiveSource(JNIEnv* env, jclass clazz, jlong handlerPtr,
- jint deviceType) {
+static void nativeSetOsdName(JNIEnv* env, jclass clazz, jlong handlerPtr, jbyteArray name) {
HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
- cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
- handler->sendInactiveSource(srcAddr);
-}
-
-static void nativeSendImageViewOn(JNIEnv* env, jclass clazz, jlong handlerPtr,
- jint deviceType) {
- HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
- cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
- handler->sendImageViewOn(srcAddr);
-}
-
-static void nativeSendTextViewOn(JNIEnv* env, jclass clazz, jlong handlerPtr,
- jint deviceType) {
- HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
- cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
- handler->sendTextViewOn(srcAddr);
-}
-
-static void nativeSendGiveDevicePowerStatus(JNIEnv* env, jclass clazz, jlong handlerPtr,
- jint deviceType, jint destination) {
- HdmiCecHandler *handler = reinterpret_cast<HdmiCecHandler *>(handlerPtr);
- cec_logical_address_t srcAddr = handler->getLogicalAddress(deviceType);
- cec_logical_address_t dstAddr = static_cast<cec_logical_address_t>(destination);
- handler->sendGiveDevicePowerStatus(srcAddr, dstAddr);
+ jsize len = env->GetArrayLength(name);
+ if (len > 0) {
+ ScopedByteArrayRO namePtr(env, name);
+ handler->setOsdName(reinterpret_cast<const char *>(namePtr.get()), len);
+ }
}
static JNINativeMethod sMethods[] = {
@@ -666,16 +616,10 @@
(void *)nativeAllocateLogicalAddress },
{ "nativeRemoveLogicalAddress", "(JI)V",
(void *)nativeRemoveLogicalAddress },
- { "nativeSendActiveSource", "(JI)V",
- (void *)nativeSendActiveSource },
- { "nativeSendInactiveSource", "(JI)V",
- (void *)nativeSendInactiveSource },
- { "nativeSendImageViewOn", "(JI)V",
- (void *)nativeSendImageViewOn },
- { "nativeSendTextViewOn", "(JI)V",
- (void *)nativeSendTextViewOn },
- { "nativeSendGiveDevicePowerStatus", "(JII)V",
- (void *)nativeSendGiveDevicePowerStatus }
+ { "nativeGetPhysicalAddress", "(J)I",
+ (void *)nativeGetPhysicalAddress },
+ { "nativeSetOsdName", "(J[B)V",
+ (void *)nativeSetOsdName },
};
#define CLASS_PATH "com/android/server/hdmi/HdmiCecService"
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f186b2c..983ca2d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -170,7 +170,7 @@
int mActivePasswordNonLetter = 0;
int mFailedPasswordAttempts = 0;
- int mUserHandle;;
+ int mUserHandle;
int mPasswordOwner = -1;
long mLastMaximumTimeToLock = -1;
@@ -722,6 +722,10 @@
final int callingUid = Binder.getCallingUid();
final int userHandle = UserHandle.getUserId(callingUid);
final DevicePolicyData policy = getUserData(userHandle);
+
+ List<ActiveAdmin> candidates = new ArrayList<ActiveAdmin>();
+
+ // Build a list of admins for this uid matching the given ComponentName
if (who != null) {
ActiveAdmin admin = policy.mAdminMap.get(who);
if (admin == null) {
@@ -731,22 +735,43 @@
throw new SecurityException("Admin " + who + " is not owned by uid "
+ Binder.getCallingUid());
}
- if (!admin.info.usesPolicy(reqPolicy)) {
- throw new SecurityException("Admin " + admin.info.getComponent()
- + " did not specify uses-policy for: "
- + admin.info.getTagForPolicy(reqPolicy));
- }
- return admin;
+ candidates.add(admin);
} else {
- final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- ActiveAdmin admin = policy.mAdminList.get(i);
- if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) {
+ for (ActiveAdmin admin : policy.mAdminList) {
+ if (admin.getUid() == callingUid) {
+ candidates.add(admin);
+ }
+ }
+ }
+
+ // Try to find an admin which can use reqPolicy
+ for (ActiveAdmin admin : candidates) {
+ boolean ownsDevice = isDeviceOwner(admin.info.getPackageName());
+ boolean ownsProfile = (getProfileOwner(userHandle) != null
+ && getProfileOwner(userHandle).equals(admin.info.getPackageName()));
+
+ if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
+ if (ownsDevice) {
+ return admin;
+ }
+ } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
+ if (ownsDevice || ownsProfile) {
+ return admin;
+ }
+ } else {
+ if (admin.info.usesPolicy(reqPolicy)) {
return admin;
}
}
+ }
+
+ if (who != null) {
+ throw new SecurityException("Admin " + candidates.get(0).info.getComponent()
+ + " did not specify uses-policy for: "
+ + candidates.get(0).info.getTagForPolicy(reqPolicy));
+ } else {
throw new SecurityException("No active admin owned by uid "
- + Binder.getCallingUid() + " for policy #" + reqPolicy);
+ + Binder.getCallingUid() + " for policy:" + reqPolicy);
}
}
@@ -2966,64 +2991,41 @@
}
}
- private boolean isProfileOwner(String packageName, int userId) {
- String profileOwnerPackage = getProfileOwner(userId);
- // TODO: make public and connect with isProfileOwnerApp in DPM
- return profileOwnerPackage != null && profileOwnerPackage.equals(packageName);
- }
-
- public void addPersistentPreferredActivity(ComponentName admin, IntentFilter filter,
+ public void addPersistentPreferredActivity(ComponentName who, IntentFilter filter,
ComponentName activity) {
- int callingUserId = UserHandle.getCallingUserId();
- Slog.d(LOG_TAG,"called by user " + callingUserId);
synchronized (this) {
- ActiveAdmin aa = getActiveAdminUncheckedLocked(admin, callingUserId);
- if (aa == null) {
- throw new SecurityException("No active admin " + admin);
- } else {
- if (isProfileOwner(admin.getPackageName(), callingUserId)
- || isDeviceOwner(admin.getPackageName())) {
- IPackageManager pm = AppGlobals.getPackageManager();
- long id = Binder.clearCallingIdentity();
- try {
- pm.addPersistentPreferredActivity(filter, activity, callingUserId);
- } catch (RemoteException re) {
- // Shouldn't happen
- } finally {
- restoreCallingIdentity(id);
- }
- } else {
- throw new SecurityException("Admin " + admin +
- "is not device owner or profile owner" );
- }
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+ IPackageManager pm = AppGlobals.getPackageManager();
+ long id = Binder.clearCallingIdentity();
+ try {
+ pm.addPersistentPreferredActivity(filter, activity, UserHandle.getCallingUserId());
+ } catch (RemoteException re) {
+ // Shouldn't happen
+ } finally {
+ restoreCallingIdentity(id);
}
}
}
- public void clearPackagePersistentPreferredActivities(ComponentName admin,
- String packageName) {
- int callingUserId = UserHandle.getCallingUserId();
- Slog.d(LOG_TAG,"called by user " + callingUserId);
+ public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
synchronized (this) {
- ActiveAdmin aa = getActiveAdminUncheckedLocked(admin, callingUserId);
- if (aa == null) {
- throw new SecurityException("No active admin " + admin);
- } else {
- if (isProfileOwner(admin.getPackageName(), callingUserId)
- || isDeviceOwner(admin.getPackageName())) {
- IPackageManager pm = AppGlobals.getPackageManager();
- long id = Binder.clearCallingIdentity();
- try{
- pm.clearPackagePersistentPreferredActivities(packageName, callingUserId);
- } catch (RemoteException re) {
- // Shouldn't happen
- } finally {
- restoreCallingIdentity(id);
- }
- } else {
- throw new SecurityException("Admin " + admin +
- "is not device owner or profile owner" );
- }
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+ IPackageManager pm = AppGlobals.getPackageManager();
+ long id = Binder.clearCallingIdentity();
+ try {
+ pm.clearPackagePersistentPreferredActivities(packageName, UserHandle.getCallingUserId());
+ } catch (RemoteException re) {
+ // Shouldn't happen
+ } finally {
+ restoreCallingIdentity(id);
}
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c925669..8f2adc8 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -50,6 +50,7 @@
import com.android.internal.R;
import com.android.internal.os.BinderInternal;
+import com.android.internal.os.Zygote;
import com.android.internal.os.SamplingProfilerIntegration;
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.accounts.AccountManagerService;
@@ -76,13 +77,13 @@
import com.android.server.search.SearchManagerService;
import com.android.server.statusbar.StatusBarManagerService;
import com.android.server.storage.DeviceStorageMonitorService;
+import com.android.server.trust.TrustManagerService;
import com.android.server.twilight.TwilightService;
import com.android.server.usb.UsbService;
import com.android.server.wallpaper.WallpaperManagerService;
import com.android.server.wm.WindowManagerService;
import dalvik.system.VMRuntime;
-import dalvik.system.Zygote;
import java.io.File;
import java.util.Timer;
@@ -116,6 +117,8 @@
"com.android.server.usb.UsbService$Lifecycle";
private static final String WIFI_SERVICE_CLASS =
"com.android.server.wifi.WifiService";
+ private static final String WIFI_HOTSPOT_SERVICE_CLASS =
+ "com.android.server.wifi.hotspot.WifiHotspotService";
private static final String WIFI_P2P_SERVICE_CLASS =
"com.android.server.wifi.p2p.WifiP2pService";
private static final String HDMI_CEC_SERVICE_CLASS =
@@ -266,7 +269,7 @@
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
- mSystemContext.setTheme(android.R.style.Theme_Holo);
+ mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}
private void startBootstrapServices() {
@@ -614,6 +617,12 @@
}
try {
+ mSystemServiceManager.startService(WIFI_HOTSPOT_SERVICE_CLASS);
+ } catch (Throwable e) {
+ reportWtf("starting Wi-Fi HotspotService", e);
+ }
+
+ try {
mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
} catch (Throwable e) {
reportWtf("starting Wi-Fi Service", e);
@@ -905,6 +914,13 @@
} catch (Throwable e) {
reportWtf("starting MediaRouterService", e);
}
+
+ try {
+ Slog.i(TAG, "Trust Manager");
+ mSystemServiceManager.startService(TrustManagerService.class);
+ } catch (Throwable e) {
+ Slog.e(TAG, "Failure starting TrustManagerService", e);
+ }
}
}
@@ -913,8 +929,6 @@
final boolean safeMode = wm.detectSafeMode();
if (safeMode) {
mActivityManagerService.enterSafeMode();
- // Post the safe mode state in the Zygote class
- Zygote.systemInSafeMode = true;
// Disable the JIT for the system_server process
VMRuntime.getRuntime().disableJitCompilation();
} else {
diff --git a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
index ce953a4..f73d425 100644
--- a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
@@ -17,8 +17,10 @@
package com.android.server.usb;
import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Resources;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.os.Handler;
@@ -244,15 +246,18 @@
}
private void showConfirmationDialog(String key, String fingerprints) {
- Intent dialogIntent = new Intent();
+ Intent intent = new Intent();
- dialogIntent.setClassName("com.android.systemui",
- "com.android.systemui.usb.UsbDebuggingActivity");
- dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- dialogIntent.putExtra("key", key);
- dialogIntent.putExtra("fingerprints", fingerprints);
+ ComponentName componentName = ComponentName.unflattenFromString(
+ Resources.getSystem().getString(
+ com.android.internal.R.string.config_customAdbPublicKeyActivity));
+ intent.setClassName(componentName.getPackageName(),
+ componentName.getClassName());
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra("key", key);
+ intent.putExtra("fingerprints", fingerprints);
try {
- mContext.startActivity(dialogIntent);
+ mContext.startActivity(intent);
} catch (ActivityNotFoundException e) {
Slog.e(TAG, "unable to start UsbDebuggingActivity");
}
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index 7ae5460..9ccb809 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -17,6 +17,7 @@
package com.android.server.usb;
import android.content.Context;
+import android.content.Intent;
import android.hardware.usb.UsbConfiguration;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
@@ -25,21 +26,25 @@
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
+import android.os.UserHandle;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import java.io.File;
import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Scanner;
/**
* UsbHostManager manages USB state in host mode.
*/
public class UsbHostManager {
private static final String TAG = UsbHostManager.class.getSimpleName();
- private static final boolean LOG = false;
+ private static final boolean DEBUG_AUDIO = false;
// contains all connected USB devices
private final HashMap<String, UsbDevice> mDevices = new HashMap<String, UsbDevice>();
@@ -102,6 +107,30 @@
return false;
}
+ // Broadcasts the arrival/departure of a USB audio interface
+ // card - the ALSA card number of the physical interface
+ // device - the ALSA device number of the physical interface
+ // enabled - if true, we're connecting a device (it's arrived), else disconnecting
+ private void sendDeviceNotification(int card, int device, boolean enabled,
+ boolean hasPlayback, boolean hasCapture, boolean hasMIDI) {
+ // send a sticky broadcast containing current USB state
+ Intent intent = new Intent(Intent.ACTION_USB_AUDIO_DEVICE_PLUG);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.putExtra("state", enabled ? 1 : 0);
+ intent.putExtra("card", card);
+ intent.putExtra("device", device);
+ intent.putExtra("hasPlayback", hasPlayback);
+ intent.putExtra("hasCapture", hasCapture);
+ intent.putExtra("hasMIDI", hasMIDI);
+ mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
+ static boolean isBuiltInUsbDevice(String deviceName) {
+ // This may be too broad an assumption
+ return deviceName.equals("/dev/bus/usb/001/001");
+ }
+
/* Called from JNI in monitorUsbHostBus() to report new USB devices
Returns true if successful, in which case the JNI code will continue adding configurations,
interfaces and endpoints, and finally call endUsbDeviceAdded after all descriptors
@@ -111,6 +140,59 @@
int deviceClass, int deviceSubclass, int deviceProtocol,
String manufacturerName, String productName, String serialNumber) {
+ if (DEBUG_AUDIO) {
+ Slog.d(TAG, "usb:UsbHostManager.beginUsbDeviceAdded(" + deviceName + ")");
+ // Audio Class Codes:
+ // Audio: 0x01
+ // Audio Subclass Codes:
+ // undefined: 0x00
+ // audio control: 0x01
+ // audio streaming: 0x02
+ // midi streaming: 0x03
+
+ // some useful debugging info
+ Slog.d(TAG, "usb:UsbHostManager.usbDeviceAdded()");
+ Slog.d(TAG, "usb: nm:" + deviceName +
+ " vnd:" + vendorID +
+ " prd:" + productID +
+ " cls:" + deviceClass +
+ " sub:" + deviceSubclass +
+ " proto:" + deviceProtocol);
+ }
+
+ if (!isBuiltInUsbDevice(deviceName)) {
+ //TODO(pmclean) we will need this when we need to support USB interfaces
+ // beyond card1, device0 but turn them off for now
+ //com.android.alsascan.AlsaCardsParser cardsParser =
+ // new com.android.alsascan.AlsaCardsParser();
+ //cardsParser.scan();
+ //cardsParser.Log();
+
+ // But we need to parse the device to determine its capabilities.
+ com.android.alsascan.AlsaDevicesParser devicesParser =
+ new com.android.alsascan.AlsaDevicesParser();
+ devicesParser.scan();
+ //devicesParser.Log();
+
+ boolean hasPlaybackDevices = devicesParser.hasPlaybackDevices();
+ boolean hasCaptureDevices = devicesParser.hasCaptureDevices();
+ boolean hasMIDI = devicesParser.hasMIDIDevices();
+
+ if (DEBUG_AUDIO) {
+ Slog.d(TAG, "usb: hasPlayback:" + hasPlaybackDevices
+ + " hasCapture:" + hasCaptureDevices);
+ }
+
+ //TODO(pmclean)
+ // For now just assume that any USB device that is attached is:
+ // 1. An audio interface and
+ // 2. is card:1 device:0
+ int cardNum = 1;
+ int deviceNum = 0;
+ sendDeviceNotification(cardNum, deviceNum, true,
+ hasPlaybackDevices, hasCaptureDevices, hasMIDI);
+ }
+
if (isBlackListed(deviceName) ||
isBlackListed(deviceClass, deviceSubclass, deviceProtocol)) {
return false;
@@ -176,6 +258,9 @@
/* Called from JNI in monitorUsbHostBus() to finish adding a new device */
private void endUsbDeviceAdded() {
+ if (DEBUG_AUDIO) {
+ Slog.d(TAG, "usb:UsbHostManager.endUsbDeviceAdded()");
+ }
if (mNewInterface != null) {
mNewInterface.setEndpoints(
mNewEndpoints.toArray(new UsbEndpoint[mNewEndpoints.size()]));
@@ -204,6 +289,13 @@
/* Called from JNI in monitorUsbHostBus to report USB device removal */
private void usbDeviceRemoved(String deviceName) {
+ if (DEBUG_AUDIO) {
+ Slog.d(TAG, "usb:UsbHostManager.usbDeviceRemoved() nm:" + deviceName);
+ }
+
+ // Same assumptions as the fake-out above
+ sendDeviceNotification(1, 0, false, /*NA*/false, /*NA*/false, /*NA*/false);
+
synchronized (mLock) {
UsbDevice device = mDevices.remove(deviceName);
if (device != null) {
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index 323e0ac..1c75658 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -101,8 +101,93 @@
/** Unknown error or not specified */
public static final int ERROR_UNSPECIFIED = 36;
+ /** Smallest valid value for call disconnect codes. */
+ public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
+ /** Largest valid value for call disconnect codes. */
+ public static final int MAXIMUM_VALID_VALUE = ERROR_UNSPECIFIED;
+
/** Private constructor to avoid class instantiation. */
private DisconnectCause() {
// Do nothing.
}
+
+ /** Returns descriptive string for the specified disconnect cause. */
+ public static String toString(int cause) {
+ switch (cause) {
+ case NOT_DISCONNECTED:
+ return "NOT_DISCONNECTED";
+ case INCOMING_MISSED:
+ return "INCOMING_MISSED";
+ case NORMAL:
+ return "NORMAL";
+ case LOCAL:
+ return "LOCAL";
+ case BUSY:
+ return "BUSY";
+ case CONGESTION:
+ return "CONGESTION";
+ case INVALID_NUMBER:
+ return "INVALID_NUMBER";
+ case NUMBER_UNREACHABLE:
+ return "NUMBER_UNREACHABLE";
+ case SERVER_UNREACHABLE:
+ return "SERVER_UNREACHABLE";
+ case INVALID_CREDENTIALS:
+ return "INVALID_CREDENTIALS";
+ case OUT_OF_NETWORK:
+ return "OUT_OF_NETWORK";
+ case SERVER_ERROR:
+ return "SERVER_ERROR";
+ case TIMED_OUT:
+ return "TIMED_OUT";
+ case LOST_SIGNAL:
+ return "LOST_SIGNAL";
+ case LIMIT_EXCEEDED:
+ return "LIMIT_EXCEEDED";
+ case INCOMING_REJECTED:
+ return "INCOMING_REJECTED";
+ case POWER_OFF:
+ return "POWER_OFF";
+ case OUT_OF_SERVICE:
+ return "OUT_OF_SERVICE";
+ case ICC_ERROR:
+ return "ICC_ERROR";
+ case CALL_BARRED:
+ return "CALL_BARRED";
+ case FDN_BLOCKED:
+ return "FDN_BLOCKED";
+ case CS_RESTRICTED:
+ return "CS_RESTRICTED";
+ case CS_RESTRICTED_NORMAL:
+ return "CS_RESTRICTED_NORMAL";
+ case CS_RESTRICTED_EMERGENCY:
+ return "CS_RESTRICTED_EMERGENCY";
+ case UNOBTAINABLE_NUMBER:
+ return "UNOBTAINABLE_NUMBER";
+ case CDMA_LOCKED_UNTIL_POWER_CYCLE:
+ return "CDMA_LOCKED_UNTIL_POWER_CYCLE";
+ case CDMA_DROP:
+ return "CDMA_DROP";
+ case CDMA_INTERCEPT:
+ return "CDMA_INTERCEPT";
+ case CDMA_REORDER:
+ return "CDMA_REORDER";
+ case CDMA_SO_REJECT:
+ return "CDMA_SO_REJECT";
+ case CDMA_RETRY_ORDER:
+ return "CDMA_RETRY_ORDER";
+ case CDMA_ACCESS_FAILURE:
+ return "CDMA_ACCESS_FAILURE";
+ case CDMA_PREEMPTED:
+ return "CDMA_PREEMPTED";
+ case CDMA_NOT_EMERGENCY:
+ return "CDMA_NOT_EMERGENCY";
+ case CDMA_ACCESS_BLOCKED:
+ return "CDMA_ACCESS_BLOCKED";
+ case ERROR_UNSPECIFIED:
+ return "ERROR_UNSPECIFIED";
+ default:
+ return "INVALID";
+ }
+ }
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 9ec7def..d5c7caa 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.PrivateApi;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
@@ -25,6 +26,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.telephony.Rlog;
import android.util.Log;
import com.android.internal.telephony.IPhoneSubInfo;
@@ -64,8 +66,41 @@
private static final String TAG = "TelephonyManager";
private static ITelephonyRegistry sRegistry;
+
+ private final HashMap<CallStateListener,Listener> mListeners
+ = new HashMap<CallStateListener,Listener>();
private final Context mContext;
+ private static class Listener extends ITelephonyListener.Stub {
+ final CallStateListener mListener;
+ private static final int WHAT = 1;
+
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ mListener.onCallStateChanged(msg.arg1, msg.arg2, (String)msg.obj);
+ }
+ };
+
+ Listener(CallStateListener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public void onUpdate(final int callId, final int state, final String number) {
+ if (mHandler != null) {
+ mHandler.sendMessage(mHandler.obtainMessage(WHAT, callId, state, number));
+ }
+ }
+
+ void clearQueue() {
+ mHandler.removeMessages(WHAT);
+
+ // Don't accept more incoming binder calls either.
+ mHandler = null;
+ }
+ }
+
/** @hide */
public TelephonyManager(Context context) {
Context appContext = context.getApplicationContext();
@@ -87,38 +122,6 @@
}
private static TelephonyManager sInstance = new TelephonyManager();
- private HashMap<CallStateListener, Listener> mListeners
- = new HashMap<CallStateListener, Listener>();
-
- private static class Listener extends ITelephonyListener.Stub {
- final CallStateListener mListener;
- private static final int WHAT = 1;
-
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- mListener.onCallStateChanged(msg.arg1, msg.arg2, (String) msg.obj);
- }
- };
-
- Listener(CallStateListener listener) {
- mListener = listener;
- }
-
- @Override
- public void onUpdate(final int callId, final int state, final String number) {
- if (mHandler != null) {
- mHandler.sendMessage(mHandler.obtainMessage(WHAT, callId, state, number));
- }
- }
-
- void clearQueue() {
- mHandler.removeMessages(WHAT);
-
- // Don't accept more incoming binder calls either.
- mHandler = null;
- }
- }
/** @hide
/* @deprecated - use getSystemService as described above */
@@ -1920,439 +1923,369 @@
* Expose the rest of ITelephony to @PrivateApi
*/
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public void dial(String number) {
try {
getITelephony().dial(number);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#dial");
+ Log.e(TAG, "Error calling ITelephony#dial", e);
}
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public void call(String callingPackage, String number) {
try {
getITelephony().call(callingPackage, number);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#call");
+ Log.e(TAG, "Error calling ITelephony#call", e);
}
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean showCallScreen() {
try {
return getITelephony().showCallScreen();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#showCallScreen");
+ Log.e(TAG, "Error calling ITelephony#showCallScreen", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean showCallScreenWithDialpad(boolean showDialpad) {
try {
return getITelephony().showCallScreenWithDialpad(showDialpad);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#showCallScreenWithDialpad");
+ Log.e(TAG, "Error calling ITelephony#showCallScreenWithDialpad", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean endCall() {
try {
return getITelephony().endCall();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#endCall");
+ Log.e(TAG, "Error calling ITelephony#endCall", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public void answerRingingCall() {
try {
getITelephony().answerRingingCall();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#answerRingingCall");
+ Log.e(TAG, "Error calling ITelephony#answerRingingCall", e);
}
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public void toggleHold() {
try {
getITelephony().toggleHold();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#toggleHold");
+ Log.e(TAG, "Error calling ITelephony#toggleHold", e);
}
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public void merge() {
try {
getITelephony().merge();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#merge");
+ Log.e(TAG, "Error calling ITelephony#merge", e);
}
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public void swap() {
try {
getITelephony().swap();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#swap");
+ Log.e(TAG, "Error calling ITelephony#swap", e);
}
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public void mute(boolean mute) {
try {
getITelephony().mute(mute);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#mute");
+ Log.e(TAG, "Error calling ITelephony#mute", e);
}
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public void silenceRinger() {
try {
getITelephony().silenceRinger();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#silenceRinger");
+ Log.e(TAG, "Error calling ITelephony#silenceRinger", e);
}
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean isOffhook() {
try {
return getITelephony().isOffhook();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#isOffhook");
+ Log.e(TAG, "Error calling ITelephony#isOffhook", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean isRinging() {
try {
return getITelephony().isRinging();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#isRinging");
+ Log.e(TAG, "Error calling ITelephony#isRinging", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean isIdle() {
try {
return getITelephony().isIdle();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#isIdle");
+ Log.e(TAG, "Error calling ITelephony#isIdle", e);
}
return true;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean isRadioOn() {
try {
return getITelephony().isRadioOn();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#isRadioOn");
+ Log.e(TAG, "Error calling ITelephony#isRadioOn", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean isSimPinEnabled() {
try {
return getITelephony().isSimPinEnabled();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#isSimPinEnabled");
+ Log.e(TAG, "Error calling ITelephony#isSimPinEnabled", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public void cancelMissedCallsNotification() {
try {
getITelephony().cancelMissedCallsNotification();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#cancelMissedCallsNotification");
+ Log.e(TAG, "Error calling ITelephony#cancelMissedCallsNotification", e);
}
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean supplyPin(String pin) {
try {
return getITelephony().supplyPin(pin);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#supplyPin");
+ Log.e(TAG, "Error calling ITelephony#supplyPin", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean supplyPuk(String puk, String pin) {
try {
return getITelephony().supplyPuk(puk, pin);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#supplyPuk");
+ Log.e(TAG, "Error calling ITelephony#supplyPuk", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public int[] supplyPinReportResult(String pin) {
try {
return getITelephony().supplyPinReportResult(pin);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#supplyPinReportResult");
+ Log.e(TAG, "Error calling ITelephony#supplyPinReportResult", e);
}
return new int[0];
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public int[] supplyPukReportResult(String puk, String pin) {
try {
return getITelephony().supplyPukReportResult(puk, pin);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#]");
+ Log.e(TAG, "Error calling ITelephony#]", e);
}
return new int[0];
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean handlePinMmi(String dialString) {
try {
return getITelephony().handlePinMmi(dialString);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#handlePinMmi");
+ Log.e(TAG, "Error calling ITelephony#handlePinMmi", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public void toggleRadioOnOff() {
try {
getITelephony().toggleRadioOnOff();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#toggleRadioOnOff");
+ Log.e(TAG, "Error calling ITelephony#toggleRadioOnOff", e);
}
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean setRadio(boolean turnOn) {
try {
return getITelephony().setRadio(turnOn);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#setRadio");
+ Log.e(TAG, "Error calling ITelephony#setRadio", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean setRadioPower(boolean turnOn) {
try {
return getITelephony().setRadioPower(turnOn);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#setRadioPower");
+ Log.e(TAG, "Error calling ITelephony#setRadioPower", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public void updateServiceLocation() {
try {
getITelephony().updateServiceLocation();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#updateServiceLocation");
+ Log.e(TAG, "Error calling ITelephony#updateServiceLocation", e);
}
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public int enableApnType(String type) {
try {
return getITelephony().enableApnType(type);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#enableApnType");
+ Log.e(TAG, "Error calling ITelephony#enableApnType", e);
}
return PhoneConstants.APN_REQUEST_FAILED;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public int disableApnType(String type) {
try {
return getITelephony().disableApnType(type);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#disableApnType");
+ Log.e(TAG, "Error calling ITelephony#disableApnType", e);
}
return PhoneConstants.APN_REQUEST_FAILED;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean enableDataConnectivity() {
try {
return getITelephony().enableDataConnectivity();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#enableDataConnectivity");
+ Log.e(TAG, "Error calling ITelephony#enableDataConnectivity", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean disableDataConnectivity() {
try {
return getITelephony().disableDataConnectivity();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#disableDataConnectivity");
+ Log.e(TAG, "Error calling ITelephony#disableDataConnectivity", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean isDataConnectivityPossible() {
try {
return getITelephony().isDataConnectivityPossible();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#isDataConnectivityPossible");
+ Log.e(TAG, "Error calling ITelephony#isDataConnectivityPossible", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public boolean needsOtaServiceProvisioning() {
try {
return getITelephony().needsOtaServiceProvisioning();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#needsOtaServiceProvisioning");
+ Log.e(TAG, "Error calling ITelephony#needsOtaServiceProvisioning", e);
}
return false;
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public void playDtmfTone(char digit, boolean timedShortCode) {
try {
getITelephony().playDtmfTone(digit, timedShortCode);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#playDtmfTone");
+ Log.e(TAG, "Error calling ITelephony#playDtmfTone", e);
}
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public void stopDtmfTone() {
try {
getITelephony().stopDtmfTone();
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#stopDtmfTone");
+ Log.e(TAG, "Error calling ITelephony#stopDtmfTone", e);
}
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public void addCallStateListener(CallStateListener listener) {
try {
if (listener == null) {
@@ -2364,14 +2297,12 @@
getITelephony().addListener(l);
}
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#addListener");
+ Log.e(TAG, "Error calling ITelephony#addListener", e);
}
}
- /**
- * @hide
- * @PrivateApi
- */
+ /** @hide */
+ @PrivateApi
public void removeCallStateListener(CallStateListener listener) {
try {
final Listener l = mListeners.remove(listener);
@@ -2381,7 +2312,7 @@
getITelephony().removeListener(l);
}
} catch (RemoteException e) {
- Log.e(TAG, "Error calling ITelephony#removeListener");
+ Log.e(TAG, "Error calling ITelephony#removeListener", e);
}
}
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyListener.aidl b/telephony/java/com/android/internal/telephony/ITelephonyListener.aidl
index 8f5441c..c226217 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyListener.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyListener.aidl
@@ -23,16 +23,5 @@
* {@hide}
*/
oneway interface ITelephonyListener {
- /**
- * Notify of a new or updated call.
- * Any time the state of a call is updated, it will alert any listeners. This includes changes
- * of state such as when a call is put on hold or conferenced.
- *
- * @param callId a unique identifier for a given call that can be used to track state changes
- * @param state the new state of the call.
- * {@see com.android.services.telephony.common.Call$State}
- * @param number the phone number of the call. For some states, this may be blank. However, it
- * will be populated for any initial state.
- */
void onUpdate(int callId, int state, String number);
}
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 118cba4..daef37a 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -16,6 +16,7 @@
package android.test.mock;
+import android.app.PackageInstallObserver;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
@@ -664,4 +665,34 @@
public VerifierDeviceIdentity getVerifierDeviceIdentity() {
throw new UnsupportedOperationException();
}
+
+ /**
+ * @hide
+ */
+ @Override
+ public void installPackage(Uri packageURI, PackageInstallObserver observer,
+ int flags, String installerPackageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void installPackageWithVerification(Uri packageURI,
+ PackageInstallObserver observer, int flags, String installerPackageName,
+ Uri verificationURI, ManifestDigest manifestDigest,
+ ContainerEncryptionParams encryptionParams) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void installPackageWithVerificationAndEncryption(Uri packageURI,
+ PackageInstallObserver observer, int flags, String installerPackageName,
+ VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/tests/SharedLibrary/client/Android.mk b/tests/SharedLibrary/client/Android.mk
index 60ef92a..1d66bb9 100644
--- a/tests/SharedLibrary/client/Android.mk
+++ b/tests/SharedLibrary/client/Android.mk
@@ -3,7 +3,7 @@
LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_APK_LIBRARIES := SharedLibrary
+LOCAL_RES_LIBRARIES := SharedLibrary
LOCAL_PACKAGE_NAME := SharedLibraryClient
diff --git a/tests/SharedLibrary/client/AndroidManifest.xml b/tests/SharedLibrary/client/AndroidManifest.xml
index c6a43c0..a39c754 100644
--- a/tests/SharedLibrary/client/AndroidManifest.xml
+++ b/tests/SharedLibrary/client/AndroidManifest.xml
@@ -16,7 +16,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.android.test.lib_client">
- <application android:label="@string/app_title">
+ <application android:label="@string/app_title" android:theme="@style/Theme">
<uses-library android:name="android.test.runner" />
<uses-library android:name="com.google.android.test.shared_library" />
<activity android:name="ActivityMain">
diff --git a/tests/SharedLibrary/client/res/layout/main.xml b/tests/SharedLibrary/client/res/layout/main.xml
new file mode 100644
index 0000000..067ef9f
--- /dev/null
+++ b/tests/SharedLibrary/client/res/layout/main.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView android:id="@+id/label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@com.google.android.test.shared_library:string/shared_string"
+ style="@com.google.android.test.shared_library:style/CodeFont"/>
+
+ <com.google.android.test.shared_library.AddressView
+ xmlns:custom="http://schemas.android.com/apk/res/com.google.android.test.shared_library"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ custom:name="Professor Android"
+ custom:streetNumber="44"
+ custom:streetName="KitKat Lane"
+ custom:city="AndroidVille"
+ custom:state="OS"
+ custom:country="Mobile"
+ custom:zip="12345"/>
+</LinearLayout>
diff --git a/tests/SharedLibrary/client/res/values/strings.xml b/tests/SharedLibrary/client/res/values/strings.xml
index 3757a25..d9efdc7 100644
--- a/tests/SharedLibrary/client/res/values/strings.xml
+++ b/tests/SharedLibrary/client/res/values/strings.xml
@@ -16,4 +16,5 @@
<resources>
<string name="app_title">SharedLibrary client</string>
+ <string name="changes">@com.google.android.test.shared_library:string/shared_string</string>
</resources>
diff --git a/tests/SharedLibrary/client/res/values/themes.xml b/tests/SharedLibrary/client/res/values/themes.xml
new file mode 100644
index 0000000..a14f98a
--- /dev/null
+++ b/tests/SharedLibrary/client/res/values/themes.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<resources>
+ <style name="Theme" parent="com.google.android.test.shared_library:Theme">
+ </style>
+</resources>
diff --git a/tests/SharedLibrary/client/src/com/google/android/test/lib_client/ActivityMain.java b/tests/SharedLibrary/client/src/com/google/android/test/lib_client/ActivityMain.java
index d6121a5..7276b3c 100644
--- a/tests/SharedLibrary/client/src/com/google/android/test/lib_client/ActivityMain.java
+++ b/tests/SharedLibrary/client/src/com/google/android/test/lib_client/ActivityMain.java
@@ -18,18 +18,33 @@
import android.app.Activity;
import android.os.Bundle;
-import android.widget.TextView;
import com.google.android.test.shared_library.SharedLibraryMain;
public class ActivityMain extends Activity {
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
- TextView content = new TextView(this);
- content.setText("Library version: " + SharedLibraryMain.getVersion(this) + "!");
+ String[] expectedAnimals = new String[] {
+ "Racoon",
+ "Rhino",
+ "Elephant"
+ };
+
+ String[] animals = getResources().getStringArray(com.google.android.test.shared_library.R.array.animals);
+ if (animals == null || animals.length != expectedAnimals.length) {
+ throw new AssertionError("Animal list from shared library is null or wrong length.");
+ }
+
+ for (int i = 0; i < expectedAnimals.length; i++) {
+ if (!expectedAnimals[i].equals(animals[i])) {
+ throw new AssertionError("Expected '" + expectedAnimals[i]
+ + "' at index " + i + " but got '" + animals[i]);
+ }
+ }
SharedLibraryMain.ensureVersion(this, SharedLibraryMain.VERSION_BASE);
- setContentView(content);
}
}
diff --git a/tests/SharedLibrary/lib/Android.mk b/tests/SharedLibrary/lib/Android.mk
index c19e23a..b2fc369 100644
--- a/tests/SharedLibrary/lib/Android.mk
+++ b/tests/SharedLibrary/lib/Android.mk
@@ -3,8 +3,13 @@
LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_AAPT_FLAGS := --shared-lib
LOCAL_PACKAGE_NAME := SharedLibrary
-LOCAL_MODULE_TAGS := tests
+LOCAL_EXPORT_PACKAGE_RESOURCES := true
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_PROGUARD_FLAG_FILES := proguard.proguard
include $(BUILD_PACKAGE)
diff --git a/tests/SharedLibrary/lib/proguard.proguard b/tests/SharedLibrary/lib/proguard.proguard
new file mode 100644
index 0000000..e5dfbe1
--- /dev/null
+++ b/tests/SharedLibrary/lib/proguard.proguard
@@ -0,0 +1,7 @@
+-keepparameternames
+-keepattributes Exceptions,InnerClasses,Signature,Deprecated,
+ SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
+
+-keep public class * {
+ public protected *;
+}
diff --git a/tests/SharedLibrary/lib/res/layout/address.xml b/tests/SharedLibrary/lib/res/layout/address.xml
new file mode 100644
index 0000000..835f43e
--- /dev/null
+++ b/tests/SharedLibrary/lib/res/layout/address.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <TextView android:id="@+id/name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ <TextView android:id="@+id/street"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ <TextView android:id="@+id/cityStateZip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ <TextView android:id="@+id/country"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+</merge>
diff --git a/tests/SharedLibrary/lib/res/values/attrs.xml b/tests/SharedLibrary/lib/res/values/attrs.xml
new file mode 100644
index 0000000..8cefe92
--- /dev/null
+++ b/tests/SharedLibrary/lib/res/values/attrs.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<resources>
+ <declare-styleable name="AddressView">
+ <attr name="name" format="string" />
+ <attr name="streetNumber" format="integer" />
+ <attr name="streetName" format="string" />
+ <attr name="city" format="string" />
+ <attr name="state" format="string" />
+ <attr name="zip" format="string" />
+ <attr name="country" format="string" />
+ </declare-styleable>
+</resources>
diff --git a/tests/SharedLibrary/lib/res/values/public.xml b/tests/SharedLibrary/lib/res/values/public.xml
new file mode 100644
index 0000000..37b1ec9
--- /dev/null
+++ b/tests/SharedLibrary/lib/res/values/public.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<resources>
+ <public type="string" name="shared_string" id="0x00020003" />
+ <public type="style" name="CodeFont" id="0x00040000" />
+ <public type="style" name="Theme" id="0x00040001" />
+
+ <public type="attr" name="name" id="0x00010000" />
+ <public type="attr" name="streetNumber" id="0x00010001" />
+ <public type="attr" name="streetName" id="0x00010002" />
+ <public type="attr" name="city" id="0x00010003" />
+ <public type="attr" name="state" id="0x00010004" />
+ <public type="attr" name="zip" id="0x00010005" />
+ <public type="attr" name="country" id="0x00010006" />
+
+ <public type="array" name="animals" id="0x02050000" />
+</resources>
diff --git a/tests/SharedLibrary/lib/res/values/strings.xml b/tests/SharedLibrary/lib/res/values/strings.xml
index bbfb0b4..6827f93 100644
--- a/tests/SharedLibrary/lib/res/values/strings.xml
+++ b/tests/SharedLibrary/lib/res/values/strings.xml
@@ -19,4 +19,13 @@
<string name="upgrade_body"><xliff:g id="app">%1$s</xliff:g> requires a newer version
of <xliff:g id="lib">%2$s</xliff:g> to run.</string>
<string name="upgrade_button">Upgrade</string>
+ <string name="shared_string">Shared string!</string>
+
+ <string-array name="animals">
+ <item>@string/racoon</item>
+ <item>Rhino</item>
+ <item>Elephant</item>
+ </string-array>
+
+ <string name="racoon">Racoon</string>
</resources>
diff --git a/tests/SharedLibrary/lib/res/values/themes.xml b/tests/SharedLibrary/lib/res/values/themes.xml
new file mode 100644
index 0000000..f1081ac
--- /dev/null
+++ b/tests/SharedLibrary/lib/res/values/themes.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<resources>
+ <style name="CodeFont" parent="@android:style/TextAppearance.Medium">
+ <item name="android:textColor">#00FF00</item>
+ <item name="android:typeface">monospace</item>
+ </style>
+
+ <style name="Theme" parent="android:Theme.Holo.Light">
+ <item name="android:actionBarStyle">@style/ActionBar</item>
+ </style>
+
+ <style name="ActionBar" parent="android:Widget.Holo.Light.ActionBar.Solid.Inverse">
+ <item name="android:background">@color/orange</item>
+ </style>
+
+ <color name="orange">#f0ad4e</color>
+</resources>
diff --git a/tests/SharedLibrary/lib/src/com/google/android/test/shared_library/AddressView.java b/tests/SharedLibrary/lib/src/com/google/android/test/shared_library/AddressView.java
new file mode 100644
index 0000000..dcaf68c
--- /dev/null
+++ b/tests/SharedLibrary/lib/src/com/google/android/test/shared_library/AddressView.java
@@ -0,0 +1,44 @@
+package com.google.android.test.shared_library;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class AddressView extends LinearLayout {
+ private TextView mNameView;
+ private TextView mStreetView;
+ private TextView mCityStateZipView;
+ private TextView mCountryView;
+
+ public AddressView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setOrientation(VERTICAL);
+
+ View view = LayoutInflater.from(context).inflate(R.layout.address, this);
+ mNameView = (TextView) view.findViewById(R.id.name);
+ mStreetView = (TextView) view.findViewById(R.id.street);
+ mCityStateZipView = (TextView) view.findViewById(R.id.cityStateZip);
+ mCountryView = (TextView) view.findViewById(R.id.country);
+
+ TypedArray a = context.getTheme().obtainStyledAttributes(
+ attrs,
+ R.styleable.AddressView,
+ 0, 0);
+ try {
+ mNameView.setText(a.getString(R.styleable.AddressView_name));
+ int streetNumber = a.getInteger(R.styleable.AddressView_streetNumber, -1);
+ mStreetView.setText((streetNumber <= 0 ? "" : Integer.toString(streetNumber)) +
+ " " + a.getString(R.styleable.AddressView_streetName));
+ mCityStateZipView.setText(a.getString(R.styleable.AddressView_city) + ", " +
+ a.getString(R.styleable.AddressView_state) + " " +
+ a.getString(R.styleable.AddressView_zip));
+ mCountryView.setText(a.getString(R.styleable.AddressView_country));
+ } finally {
+ a.recycle();
+ }
+ }
+}
diff --git a/tests/VectorDrawableTest/Android.mk b/tests/VectorDrawableTest/Android.mk
new file mode 100644
index 0000000..dd8a4d4
--- /dev/null
+++ b/tests/VectorDrawableTest/Android.mk
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := VectorDrawableTest
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_PACKAGE)
diff --git a/tests/VectorDrawableTest/AndroidManifest.xml b/tests/VectorDrawableTest/AndroidManifest.xml
new file mode 100644
index 0000000..06effe2
--- /dev/null
+++ b/tests/VectorDrawableTest/AndroidManifest.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.dynamic" >
+ <uses-sdk android:minSdkVersion="11" />
+
+ <application
+ android:hardwareAccelerated="true"
+ android:label="vector" >
+ <activity
+ android:name="VectorDrawableTest"
+ android:label="Vector Icon" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name="VectorDrawable01"
+ android:label="VectorTest1" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity
+ android:name="VectorDrawablePerformance"
+ android:label="Vector Performance" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+
+ <activity
+ android:name="VectorDrawableDupPerf"
+ android:label="Vector Performance of clones" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+ <activity
+ android:name="VectorDrawableStaticPerf"
+ android:label="Performance of vector images" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+
+ <activity
+ android:name="VectorCheckbox"
+ android:label="On a Checkbox" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+ <activity
+ android:name="VectorPathChecking"
+ android:label="Path Checking graphics" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+ </application>
+
+</manifest>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable-hdpi/icon.png b/tests/VectorDrawableTest/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..60fbdf5
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/tests/VectorDrawableTest/res/drawable/icon.png b/tests/VectorDrawableTest/res/drawable/icon.png
new file mode 100644
index 0000000..cb40a19
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/icon.png
Binary files differ
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
new file mode 100644
index 0000000..538993f
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
@@ -0,0 +1,73 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:trigger="state_checked" android:versionCode="1" >
+
+ <size
+ android:height="64dp"
+ android:width="64dp" />
+
+ <viewport
+ android:viewportHeight="480"
+ android:viewportWidth="480" />
+
+ <group>
+ <path
+ android:name="check"
+ android:pathData="m20,200l100,90l180,-180l-35,-35l-145,145l-60,-60l-40,40z"
+ android:fill="#ffff00ff"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="5" />
+ </group>
+ <group>
+ <path
+ android:name="box1"
+ android:pathData="m127,171l37,38l33,-31l-37,-40l-1,3l-2,0l-30,30z"
+ android:fill="#ffffffff"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="5" />
+ </group>
+ <group>
+ <path
+ android:name="box2"
+ android:pathData="m127,171l37,38l33,-31l-37,-40l-1,3l-2,0l-30,30z"
+ android:fill="#ff000000"
+ android:rotation="46.757"
+ android:pivotX="162"
+ android:pivotY="173.5"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="5" />
+ </group>
+ <group>
+ <path
+ android:name="box3"
+ android:pathData="m187,147l-1,55l-49,-1l2,-53l48,0z"
+ android:stroke="#FF000000"
+ android:strokeWidth="4" />
+ </group>
+ <group>
+ <path
+ android:name="box4"
+ android:pathData="m248,74l0,164l-177,0l1,-165l173,-1l3,2z"
+ android:stroke="#FF000000"
+ android:strokeWidth="30" />
+ </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
new file mode 100644
index 0000000..49906d17
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable02.xml
@@ -0,0 +1,46 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="320"
+ android:viewportHeight="320"/>
+
+ <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"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="10"
+ android:rotation="180"
+ android:pivotX="70"
+ android:pivotY="120"
+ 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
new file mode 100644
index 0000000..137049d
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable03.xml
@@ -0,0 +1,137 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport
+ android:viewportWidth="7.30625"
+ android:viewportHeight="12.25"/>
+
+ <group>
+
+ <path
+ android:name="clip1"
+ android:pathData="
+ M 0, 0
+ l 7.3, 0
+ l 0, 0
+ 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, 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="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>
+ <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
new file mode 100644
index 0000000..cffb73f
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml
@@ -0,0 +1,126 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport
+ android:viewportWidth="7.30625"
+ android:viewportHeight="12.25"/>
+
+ <group>
+ <path
+ android:name="clip1"
+ 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="#112233"
+ />
+
+ <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 -6, 0
+ a 6,6 0 1,0 12,0
+ a 6,6 0 1,0 -12,0z"
+ android:clipToPath="true"
+ android:fill="#112233"
+ />
+ <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>
+ <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
new file mode 100644
index 0000000..bcf3ae6
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
@@ -0,0 +1,147 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport
+ android:viewportWidth="7.30625"
+ android:viewportHeight="12.25"/>
+
+ <group>
+ <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="#ffff00"
+ />
+
+
+ <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="#ffff00"
+ android:fillOpacity="0"
+ />
+ </group>
+ <group>
+ <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="#ffff00"
+ android:fillOpacity="0"
+ />
+ <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="#ffff00"
+ />
+ </group>
+ <group>
+ <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="#ffff00"
+ />
+ <path
+ android:name="three"
+ 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"
+ android:fill="#ffff00"
+ android:fillOpacity="0"
+ />
+ </group>
+ <group>
+ <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="#ffff00"
+ android:fillOpacity="0"
+ />
+ <path
+ android:name="three"
+ 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"
+ android:fill="#ffff00"
+ />
+ </group>
+
+
+ <animation
+ android:sequence="one,one,three,three"
+ android:durations="2000,0,2000"/>
+ <animation
+ android:sequence="two,two,two,two"
+ android:durations="2000,0,2000"/>
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml
new file mode 100644
index 0000000..73ff5e2
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml
@@ -0,0 +1,76 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport
+ android:viewportWidth="700"
+ 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"
+ 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="#FFFFFFFF"
+ 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>
+
+ <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
new file mode 100644
index 0000000..99d37ef
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml
@@ -0,0 +1,45 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <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"
+ android:pathData="M 20,55 l 35.3,-35.3 7.07,7.07 -35.3,35.3 z
+ 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
new file mode 100644
index 0000000..f8a03d7
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable08.xml
@@ -0,0 +1,48 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+
+ <viewport android:viewportWidth="600"
+ android:viewportHeight="600"/>
+
+ <group>
+ <path
+ android:name="pie1"
+ android:pathData="M535.441,412.339A280.868,280.868 0 1,1 536.186,161.733L284.493,286.29Z"
+ android:fill="#ffffcc00"
+ android:stroke="#FF00FF00"
+ 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
new file mode 100644
index 0000000..09934de
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml
@@ -0,0 +1,41 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+
+ <viewport android:viewportWidth="200"
+ android:viewportHeight="200"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M 20,20 l 60,0 0,140 -60,0 z M 120,20 l 60,0 0,140 -60,0 z"
+ android:fill="#ffffffff"/>
+ </group>
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M 100,20 l 0,0 0,140 -80,0 z M 100,20 l 0,0 80,140 -80,0 z"
+ android:fill="#ffffffff"
+ android:rotation="90"
+ android:pivotX="100"
+ android:pivotY="100"/>
+ </group>
+ <animation android:sequence="arrow,house"/>
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml
new file mode 100644
index 0000000..f17f67a
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:height="64dp"
+ android:width="64dp" />
+
+ <viewport
+ android:viewportHeight="200"
+ android:viewportWidth="200" />
+
+ <group>
+ <path
+ android:name="bar3"
+ 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"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar2"
+ 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"
+ android:fill="#FF555555" />
+ <path
+ android:name="bar1"
+ 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"
+ android:fill="#FF555555" />
+ <path
+ android:name="bar0"
+ 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"
+ android:fill="#FF555555" />
+ </group>
+ <group>
+ <path
+ android:name="bar3"
+ 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"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar2"
+ 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"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar1"
+ 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"
+ android:fill="#FF555555" />
+ <path
+ android:name="bar0"
+ 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"
+ android:fill="#FF555555" />
+ </group>
+
+ <group>
+ <path
+ android:name="bar3"
+ 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"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar2"
+ 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"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar1"
+ 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"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar0"
+ 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"
+ android:fill="#FF555555" />
+ </group>
+
+ <group>
+ <path
+ android:name="bar3"
+ 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"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar2"
+ 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"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar1"
+ 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"
+ android:fill="#FFFFFFFF" />
+ <path
+ android:name="bar0"
+ 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"
+ android:fill="#FFFFFFFF" />
+ </group>
+
+ <animation
+ android:sequence="bar0,bar0,bar0,bar0"
+ android:durations="500,500,500"/>
+ <animation
+ android:sequence="bar1,bar1,bar1,bar1"
+ android:durations="500,500,500"/>
+ <animation
+ android:sequence="bar2,bar2,bar2,bar2"
+ android:durations="500,500,500"/>
+ <animation
+ android:sequence="bar3,bar3,bar3,bar3"
+ android:durations="500,500,500"/>
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml
new file mode 100644
index 0000000..8787b34
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml
@@ -0,0 +1,62 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:height="64dp"
+ android:width="64dp" />
+
+ <viewport
+ android:viewportHeight="80"
+ android:viewportWidth="40" />
+
+ <group>
+ <path
+ android:name="battery"
+ 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:fill="#3388ff"
+ android:stroke="#ff8833"
+ android:strokeWidth="1"
+ android:rotation="0"/>
+ <path
+ android:name="spark"
+ 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"
+ android:fill="#FFFF0000" />
+
+ </group>
+ <group>
+ <path
+ android:name="battery"
+ 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:fill="#ff8833"
+ android:stroke="#3388ff"
+ android:strokeWidth="1"
+ android:rotation="0" />
+ <path
+ android:name="spark"
+ 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"
+ android:fill="#FFFF0000" />
+ </group>
+
+ <animation
+ android:durations="2000"
+ android:sequence="spark,spark" />
+ <animation
+ android:durations="2000"
+ android:sequence="battery,battery" />
+
+
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
new file mode 100644
index 0000000..89748d5
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
@@ -0,0 +1,90 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+
+ <viewport android:viewportWidth="600"
+ android:viewportHeight="600"/>
+
+ <group>
+ <path
+ android:name="pie1"
+ android:pathData="M300,70 a230,230 0 1,0 1,0 z"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="70"
+ android:trimPathStart="0"
+ android:trimPathEnd=".75"
+ android:trimPathOffset="0"/>
+
+ <path
+ android:name="v"
+ android:pathData="M300,70 l 0,-70 70,70 -70,70z"
+ android:fill="#FF00FF00"
+ android:pivotX="300"
+ 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:stroke="#FF00FF00"
+ android:strokeWidth="70"
+ android:rotation="360"
+ android:pivotX="300"
+ android:pivotY="300"
+ android:trimPathStart="0"
+ android:trimPathEnd=".5"
+ android:trimPathOffset="0"
+ android:strokeLineCap="round"
+ />
+ </group>
+
+ <animation android:sequence="pie1,pie2"
+ android:durations="2000"
+ android:startOffset="500"
+ android:repeatCount="-1"
+ android:repeatStyle="forward"
+ android:animate="easeInOut"
+ />
+ <animation android:sequence="v,v"
+ android:durations="2000"
+ android:startOffset="500"
+ android:repeatCount="-1"
+ android:repeatStyle="forward"
+ android:animate="easeInOut"
+ />
+ <animation android:sequence="pie1,pie2"
+ android:durations="2800"
+ android:startOffset="500"
+ android:limitTo="trimPathEnd"
+ android:repeatCount="-1"
+ android:repeatStyle="reverse"
+ android:animate="easeInOut"
+ />
+
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml
new file mode 100644
index 0000000..43dda52
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml
@@ -0,0 +1,82 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+
+ <viewport android:viewportWidth="600"
+ android:viewportHeight="400"/>
+
+ <group>
+ <path
+ android:name="pie1"
+ android:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z"
+ android:fill="#ffffffff"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="1"/>
+
+ <path
+ android:name="half"
+ android:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z"
+ android:fill="#FFFF0000"
+ android:stroke="#FF0000FF"
+ android:strokeWidth="5"
+ android:rotation="0"
+ android:pivotX="300"
+ android:pivotY="200"/>
+ </group>
+
+ <group>
+ <path
+ android:name="pie2"
+ android:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z"
+ android:fill="#ffff0000"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="10"
+ android:rotation="360"
+ android:pivotX="300"
+ android:pivotY="200"/>
+
+ <path
+ android:name="half"
+ android:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z"
+ android:fill="#FFFFFF00"
+ android:stroke="#FF0000FF"
+ android:strokeWidth="5"
+ android:rotation="-360"
+ android:pivotX="300"
+ android:pivotY="200"/>
+ </group>
+ <animation android:sequence="pie1,pie2"
+ android:durations="1000"
+ android:startOffset="500"
+ android:repeatCount="2"
+ android:repeatStyle="forward"
+ android:animate="easeInOut"
+ />
+ <animation android:sequence="half,half"
+ android:durations="1000"
+ android:startOffset="500"
+ android:repeatCount="5"
+ android:repeatStyle="forward"
+ android:animate="easeInOut"
+ />
+
+
+
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
new file mode 100644
index 0000000..0f1f149
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
@@ -0,0 +1,54 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="800"
+ android:viewportHeight="500"/>
+
+ <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
+ a25,25 -30 0,1 100,-50 l 50,-25
+ a25,37 -30 0,1 100,-50 l 50,-25
+ a25,50 -30 0,1 100,-50 l 50,-25"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="10"
+ android:rotation="20"
+ android:pivotX="90"
+ android:pivotY="100"/>
+
+ </group>
+ <animation android:sequence="pie1,pie2"/>
+
+
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml
new file mode 100644
index 0000000..6bc946f
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml
@@ -0,0 +1,48 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="500"
+ android:viewportHeight="400"/>
+
+ <group>
+ <path
+ android:name="arrow"
+ android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+ android:fill="#ffffffff"
+ android:stroke="#FFFF0000"
+ android:strokeWidth="1"/>
+ </group>
+
+ <group>
+ <path
+ android:name="house"
+ android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+ android:fill="#ff440000"
+ android:stroke="#FFFF0000"
+ android:strokeWidth="10"
+ android:rotation="180"
+ android:pivotX="250"
+ android:pivotY="200"/>
+ </group>
+
+ <animation android:sequence="arrow,house"/>
+
+
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml
new file mode 100644
index 0000000..c9c8e8a
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml
@@ -0,0 +1,46 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="200"
+ android:viewportHeight="200"/>
+
+ <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:stroke="#FF00FF00"
+ android:strokeWidth="10"
+ android:rotation="360"
+ android:pivotX="100"
+ android:pivotY="100"/>
+ </group>
+
+ <animation android:sequence="arrow,house"/>
+
+
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml
new file mode 100644
index 0000000..9427652
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml
@@ -0,0 +1,46 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="1200"
+ android:viewportHeight="600"/>
+
+ <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"
+ android:strokeWidth="10"
+ android:rotation="360"
+ android:pivotX="600"
+ 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
new file mode 100644
index 0000000..83dfbd2
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml
@@ -0,0 +1,45 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="500"
+ android:viewportHeight="400"/>
+
+ <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:strokeWidth="10"
+ android:rotation="360"
+ android:pivotX="250"
+ android:pivotY="200"/>
+ </group>
+
+ <animation android:sequence="arrow,house"/>
+
+
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
new file mode 100644
index 0000000..013254f
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
@@ -0,0 +1,45 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="1000"
+ android:viewportHeight="800"/>
+
+ <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:stroke="#FFFF0000"
+ android:strokeWidth="60"
+ android:pivotX="90"
+ android:pivotY="100"/>
+ </group>
+
+ <animation android:sequence="arrow,house"/>
+
+
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable20.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable20.xml
new file mode 100644
index 0000000..aba7e5f
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable20.xml
@@ -0,0 +1,37 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:width="64dp"
+ android:height="64dp"/>
+
+ <viewport android:viewportWidth="480"
+ android:viewportHeight="480"/>
+
+ <group>
+ <path
+ android:name="edit"
+ android:pathData="M406.667,180c0,0 -100 -100 -113.334 -113.333
+ c-13.333 -13.334 -33.333,0 -33.333,0l-160,160c0,0 -40,153.333 -40,173.333c0,13.333,13.333,13.333,13.333,13.333l173.334 -40
+ c0,0,146.666 -146.666,160 -160C420,200,406.667,180,406.667,180z M226.399,356.823L131.95,378.62l-38.516 -38.522
+ c7.848 -34.675,20.152 -82.52,23.538 -95.593l3.027,2.162l106.667,106.666L226.399,356.823z"
+ android:stroke="#FF000000"
+ android:fill="#FF00FFFF"
+ android:strokeWidth="10"/>
+ </group>
+
+
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_create.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_create.xml
new file mode 100644
index 0000000..8897181
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_create.xml
@@ -0,0 +1,29 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="64dp"
+android:height="64dp"/>
+
+ <viewport android:viewportWidth="24"
+ android:viewportHeight="24"/>
+
+<group>
+<path
+ android:pathData="M3.0,17.25L3.0,21.0l3.75,0.0L17.813995,9.936001l-3.75,-3.75L3.0,17.25zM20.707,7.0429993c0.391,-0.391 0.391,-1.023 0.0,-1.414l-2.336,-2.336c-0.391,-0.391 -1.023,-0.391 -1.414,0.0l-1.832,1.832l3.75,3.75L20.707,7.0429993z"
+ android:fill="#FF000000"
+ />
+</group>
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_delete.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_delete.xml
new file mode 100644
index 0000000..2c7ebbd
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_delete.xml
@@ -0,0 +1,29 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="64dp"
+android:height="64dp"/>
+
+ <viewport android:viewportWidth="24"
+ android:viewportHeight="24"/>
+
+<group>
+<path
+ android:pathData="M6.0,19.0c0.0,1.104 0.896,2.0 2.0,2.0l8.0,0.0c1.104,0.0 2.0,-0.896 2.0,-2.0l0.0,-12.0L6.0,7.0L6.0,19.0zM18.0,4.0l-2.5,0.0l-1.0,-1.0l-5.0,0.0l-1.0,1.0L6.0,4.0C5.4469986,4.0 5.0,4.4469986 5.0,5.0l0.0,1.0l14.0,0.0l0.0,-1.0C19.0,4.4469986 18.552002,4.0 18.0,4.0z"
+ android:fill="#FF000000"
+ />
+</group>
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_heart.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_heart.xml
new file mode 100644
index 0000000..e4cf78c
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_heart.xml
@@ -0,0 +1,29 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="64dp"
+android:height="64dp"/>
+
+ <viewport android:viewportWidth="24"
+ android:viewportHeight="24"/>
+
+<group>
+<path
+ android:pathData="M16.0,5.0c-1.955,0.0 -3.83,1.268 -4.5,3.0c-0.67,-1.732 -2.547,-3.0 -4.5,-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207,-5.242 9.0,-7.971 9.0,-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z"
+ android:fill="#FF000000"
+ />
+</group>
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml
new file mode 100644
index 0000000..cec12ba
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml
@@ -0,0 +1,33 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="64dp"
+android:height="64dp"/>
+
+ <viewport android:viewportWidth="24"
+ android:viewportHeight="24"/>
+
+<group>
+<path
+ android:pathData="M11.994999,2.0C6.4679985,2.0 2.0,6.4780006 2.0,12.0s4.468,10.0 9.995,10.0S22.0,17.522 22.0,12.0S17.521,2.0 11.994999,2.0zM12.0,20.0c-4.42,0.0 -8.0,-3.582 -8.0,-8.0s3.58,-8.0 8.0,-8.0s8.0,3.582 8.0,8.0S16.419998,20.0 12.0,20.0z"
+ android:fillOpacity="0.9"
+ />
+<path
+ android:pathData="M12.5,6.0l-1.5,0.0 0.0,7.0 5.3029995,3.1819992 0.75,-1.249999 -4.5529995,-2.7320004z"
+ android:fillOpacity="0.9"
+ />
+</group>
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_settings.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_settings.xml
new file mode 100644
index 0000000..5fe1fb6
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_settings.xml
@@ -0,0 +1,29 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="64dp"
+android:height="64dp"/>
+
+ <viewport android:viewportWidth="24"
+ android:viewportHeight="24"/>
+
+<group>
+<path
+ android:pathData="M19.429,12.975998c0.042,-0.32 0.07,-0.645 0.07,-0.976s-0.029,-0.655 -0.07,-0.976l2.113,-1.654c0.188,-0.151 0.243,-0.422 0.118,-0.639l-2.0,-3.463c-0.125,-0.217 -0.386,-0.304 -0.612,-0.218l-2.49,1.004c-0.516,-0.396 -1.081,-0.731 -1.69,-0.984l-0.375,-2.648C14.456,2.1829987 14.25,2.0 14.0,2.0l-4.0,0.0C9.75,2.0 9.544,2.1829987 9.506,2.422001L9.131,5.0699997C8.521,5.322998 7.957,5.6570015 7.44,6.054001L4.952,5.0509987C4.726,4.965 4.464,5.052002 4.34,5.269001l-2.0,3.463C2.2150002,8.947998 2.27,9.219002 2.4580002,9.369999l2.112,1.653C4.528,11.344002 4.5,11.668999 4.5,12.0s0.029,0.656 0.071,0.977L2.4580002,14.630001c-0.188,0.151 -0.243,0.422 -0.118,0.639l2.0,3.463c0.125,0.217 0.386,0.304 0.612,0.218l2.489,-1.004c0.516,0.396 1.081,0.731 1.69,0.984l0.375,2.648C9.544,21.817001 9.75,22.0 10.0,22.0l4.0,0.0c0.25,0.0 0.456,-0.183 0.494,-0.422l0.375,-2.648c0.609,-0.253 1.174,-0.588 1.689,-0.984l2.49,1.004c0.226,0.086 0.487,-0.001 0.612,-0.218l2.0,-3.463c0.125,-0.217 0.07,-0.487 -0.118,-0.639L19.429,12.975998zM12.0,16.0c-2.21,0.0 -4.0,-1.791 -4.0,-4.0c0.0,-2.21 1.79,-4.0 4.0,-4.0c2.208,0.0 4.0,1.79 4.0,4.0C16.0,14.209 14.208,16.0 12.0,16.0z"
+ android:fill="#FF000000"
+ />
+</group>
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_test01.xml b/tests/VectorDrawableTest/res/drawable/vector_test01.xml
new file mode 100644
index 0000000..6beb9d8
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_test01.xml
@@ -0,0 +1,31 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="128dp"
+android:height="128dp"/>
+
+ <viewport android:viewportWidth="512"
+ android:viewportHeight="512"/>
+
+<group>
+<path
+ android:name="002b"
+ android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0t-200,299"
+ android:stroke="#FF0000FF"
+ android:strokeWidth="4"
+ />
+</group>
+</vector>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_test02.xml b/tests/VectorDrawableTest/res/drawable/vector_test02.xml
new file mode 100644
index 0000000..2c1a28e
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_test02.xml
@@ -0,0 +1,31 @@
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+<size
+android:width="128dp"
+android:height="128dp"/>
+
+ <viewport android:viewportWidth="512"
+ android:viewportHeight="512"/>
+
+<group>
+<path
+ android:name="002b"
+ android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0T-200,299"
+ android:stroke="#FF0000FF"
+ android:strokeWidth="4"
+ />
+</group>
+</vector>
diff --git a/core/res/res/drawable/item_background_borderless_quantum_dark.xml b/tests/VectorDrawableTest/res/values/strings.xml
similarity index 84%
copy from core/res/res/drawable/item_background_borderless_quantum_dark.xml
copy to tests/VectorDrawableTest/res/values/strings.xml
index 3f32850..64163c2 100644
--- a/core/res/res/drawable/item_background_borderless_quantum_dark.xml
+++ b/tests/VectorDrawableTest/res/values/strings.xml
@@ -14,5 +14,5 @@
limitations under the License.
-->
-<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="@color/lighter_gray" />
+<resources>
+</resources>
diff --git a/core/res/res/drawable/item_background_borderless_quantum_dark.xml b/tests/VectorDrawableTest/res/values/styles.xml
similarity index 79%
copy from core/res/res/drawable/item_background_borderless_quantum_dark.xml
copy to tests/VectorDrawableTest/res/values/styles.xml
index 3f32850..460c0db 100644
--- a/core/res/res/drawable/item_background_borderless_quantum_dark.xml
+++ b/tests/VectorDrawableTest/res/values/styles.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,6 +12,5 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="@color/lighter_gray" />
+<resources>
+</resources>
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java
new file mode 100644
index 0000000..0b3ea4d
--- /dev/null
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorCheckbox.java
@@ -0,0 +1,68 @@
+/*
+ * 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.test.dynamic;
+
+import android.app.Activity;
+import android.graphics.drawable.VectorDrawable;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.GridLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorCheckbox extends Activity {
+ private static final String LOGCAT = "VectorDrawable1";
+ int[] icon = {
+ R.drawable.vector_drawable01,
+ R.drawable.vector_drawable02,
+ R.drawable.vector_drawable03,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable05,
+ R.drawable.vector_drawable06,
+ R.drawable.vector_drawable07,
+ R.drawable.vector_drawable08,
+ R.drawable.vector_drawable09,
+ R.drawable.vector_drawable10,
+ R.drawable.vector_drawable11,
+ R.drawable.vector_drawable12,
+ R.drawable.vector_drawable13,
+ R.drawable.vector_drawable14,
+ R.drawable.vector_drawable15,
+ R.drawable.vector_drawable16,
+ R.drawable.vector_drawable17,
+ R.drawable.vector_drawable18,
+ R.drawable.vector_drawable19,
+ R.drawable.vector_drawable20
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ GridLayout container = new GridLayout(this);
+ container.setColumnCount(5);
+ container.setBackgroundColor(0xFF888888);
+ final Button []bArray = new Button[icon.length];
+
+ for (int i = 0; i < icon.length; i++) {
+ CheckBox checkBox = new CheckBox(this);
+ bArray[i] = checkBox;
+ checkBox.setWidth(200);
+ checkBox.setButtonDrawable(icon[i]);
+ container.addView(checkBox);
+ }
+ setContentView(container);
+ }
+}
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
new file mode 100644
index 0000000..88ae398
--- /dev/null
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
@@ -0,0 +1,88 @@
+/*
+ * 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.test.dynamic;
+
+import android.app.Activity;
+import android.graphics.drawable.VectorDrawable;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.GridLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorDrawable01 extends Activity implements View.OnClickListener {
+ private static final String LOGCAT = "VectorDrawable1";
+ int[] icon = {
+ R.drawable.vector_drawable01,
+ R.drawable.vector_drawable02,
+ R.drawable.vector_drawable03,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable05,
+ R.drawable.vector_drawable06,
+ R.drawable.vector_drawable07,
+ R.drawable.vector_drawable08,
+ R.drawable.vector_drawable09,
+ R.drawable.vector_drawable10,
+ R.drawable.vector_drawable11,
+ R.drawable.vector_drawable12,
+ R.drawable.vector_drawable13,
+ R.drawable.vector_drawable14,
+ R.drawable.vector_drawable15,
+ R.drawable.vector_drawable16,
+ R.drawable.vector_drawable17,
+ R.drawable.vector_drawable18,
+ R.drawable.vector_drawable19,
+ R.drawable.vector_drawable20
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ GridLayout container = new GridLayout(this);
+ container.setColumnCount(5);
+ container.setBackgroundColor(0xFF888888);
+ final Button []bArray = new Button[icon.length];
+
+ for (int i = 0; i < icon.length; i++) {
+ Button button = new Button(this);
+ bArray[i] = button;
+ button.setWidth(200);
+ button.setBackgroundResource(icon[i]);
+ container.addView(button);
+ button.setOnClickListener(this);
+ }
+ Button b = new Button(this);
+ b.setText("Run All");
+ b.setOnClickListener(new View.OnClickListener(){
+
+ @Override
+ public void onClick(View v) {
+ for (int i = 0; i < bArray.length; i++) {
+ VectorDrawable d = (VectorDrawable) bArray[i].getBackground();
+ d.start();
+ }
+ }});
+ container.addView(b);
+ setContentView(container);
+
+ }
+
+ @Override
+ public void onClick(View v) {
+ VectorDrawable d = (VectorDrawable) v.getBackground();
+ d.start();
+ }
+
+}
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java
new file mode 100644
index 0000000..a00bc5e
--- /dev/null
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableDupPerf.java
@@ -0,0 +1,43 @@
+/*
+ * 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.test.dynamic;
+
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorDrawableDupPerf extends VectorDrawablePerformance {
+ {
+ icon = new int[]{
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable04,
+ };
+ }
+}
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
new file mode 100644
index 0000000..3929298
--- /dev/null
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -0,0 +1,94 @@
+/*
+ * 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.test.dynamic;
+
+import android.app.Activity;
+import android.content.res.Resources;
+import android.graphics.drawable.VectorDrawable;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Button;
+import android.widget.GridLayout;
+import android.widget.ScrollView;
+import java.text.DecimalFormat;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorDrawablePerformance extends Activity implements View.OnClickListener {
+ private static final String LOGCAT = "VectorDrawable1";
+ protected int[] icon = {
+ R.drawable.vector_drawable01,
+ R.drawable.vector_drawable02,
+ R.drawable.vector_drawable03,
+ R.drawable.vector_drawable04,
+ R.drawable.vector_drawable05,
+ R.drawable.vector_drawable06,
+ R.drawable.vector_drawable07,
+ R.drawable.vector_drawable08,
+ R.drawable.vector_drawable09,
+ R.drawable.vector_drawable10,
+ R.drawable.vector_drawable11,
+ R.drawable.vector_drawable12,
+ R.drawable.vector_drawable13,
+ R.drawable.vector_drawable14,
+ R.drawable.vector_drawable15,
+ R.drawable.vector_drawable16,
+ R.drawable.vector_drawable17,
+ R.drawable.vector_drawable18,
+ R.drawable.vector_drawable19,
+ R.drawable.vector_drawable20
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ScrollView scrollView = new ScrollView(this);
+ GridLayout container = new GridLayout(this);
+ scrollView.addView(container);
+ container.setColumnCount(5);
+ Resources res = this.getResources();
+ container.setBackgroundColor(0xFF888888);
+ VectorDrawable []d = new VectorDrawable[icon.length];
+ long time = android.os.SystemClock.elapsedRealtimeNanos();
+ for (int i = 0; i < icon.length; i++) {
+ d[i] = VectorDrawable.create(res,icon[i]);
+ }
+ time = android.os.SystemClock.elapsedRealtimeNanos()-time;
+ TextView t = new TextView(this);
+ DecimalFormat df = new DecimalFormat("#.##");
+ t.setText("avgL=" + df.format(time / (icon.length * 1000000.)) + " ms");
+ t.setBackgroundColor(0xFF000000);
+ container.addView(t);
+ time = android.os.SystemClock.elapsedRealtimeNanos();
+ for (int i = 0; i < icon.length; i++) {
+ Button button = new Button(this);
+ button.setWidth(200);
+ button.setBackgroundResource(icon[i]);
+ container.addView(button);
+ button.setOnClickListener(this);
+ }
+ setContentView(scrollView);
+ time = android.os.SystemClock.elapsedRealtimeNanos()-time;
+ t = new TextView(this);
+ t.setText("avgS=" + df.format(time / (icon.length * 1000000.)) + " ms");
+ t.setBackgroundColor(0xFF000000);
+ container.addView(t);
+ }
+
+ @Override
+ public void onClick(View v) {
+ VectorDrawable d = (VectorDrawable) v.getBackground();
+ d.start();
+ }
+}
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java
new file mode 100644
index 0000000..9d3eded
--- /dev/null
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableStaticPerf.java
@@ -0,0 +1,36 @@
+/*
+ * 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.test.dynamic;
+
+import android.app.Activity;
+import android.content.res.Resources;
+import android.graphics.drawable.VectorDrawable;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Button;
+import android.widget.GridLayout;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorDrawableStaticPerf extends VectorDrawablePerformance {
+ {
+ icon = new int[]{
+ R.drawable.vector_icon_create,
+ R.drawable.vector_icon_delete,
+ R.drawable.vector_icon_heart,
+ R.drawable.vector_icon_schedule,
+ R.drawable.vector_icon_settings,
+ };
+ }
+}
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java
new file mode 100644
index 0000000..704d3d7
--- /dev/null
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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.test.dynamic;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@SuppressWarnings("UnusedDeclaration")
+public class VectorDrawableTest extends android.app.ListActivity {
+ private static final String EXTRA_PATH = "com.android.test.dynamic.Path";
+ private static final String CATEGORY_HWUI_TEST = "com.android.test.dynamic.TEST";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Intent intent = getIntent();
+ String path = intent.getStringExtra("com.android.test.hwui.Path");
+
+ if (path == null) {
+ path = "";
+ }
+
+ setListAdapter(new SimpleAdapter(this, getData(path),
+ android.R.layout.simple_list_item_1, new String[] { "title" },
+ new int[] { android.R.id.text1 }));
+ getListView().setTextFilterEnabled(true);
+ }
+
+ protected List<Map<String, Object>> getData(String prefix) {
+ List<Map<String, Object>> myData = new ArrayList<Map<String, Object>>();
+
+ Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(CATEGORY_HWUI_TEST);
+
+ PackageManager pm = getPackageManager();
+ List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);
+
+ if (null == list)
+ return myData;
+
+ String[] prefixPath;
+ String prefixWithSlash = prefix;
+
+ if (prefix.equals("")) {
+ prefixPath = null;
+ } else {
+ prefixPath = prefix.split("/");
+ prefixWithSlash = prefix + "/";
+ }
+
+ int len = list.size();
+
+ Map<String, Boolean> entries = new HashMap<String, Boolean>();
+
+ for (int i = 0; i < len; i++) {
+ ResolveInfo info = list.get(i);
+ CharSequence labelSeq = info.loadLabel(pm);
+ String label = labelSeq != null
+ ? labelSeq.toString()
+ : info.activityInfo.name;
+
+ if (prefixWithSlash.length() == 0 || label.startsWith(prefixWithSlash)) {
+
+ String[] labelPath = label.split("/");
+
+ String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length];
+
+ if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) {
+ addItem(myData, nextLabel, activityIntent(
+ info.activityInfo.applicationInfo.packageName,
+ info.activityInfo.name));
+ } else {
+ if (entries.get(nextLabel) == null) {
+ addItem(myData, nextLabel, browseIntent(prefix.equals("") ?
+ nextLabel : prefix + "/" + nextLabel));
+ entries.put(nextLabel, true);
+ }
+ }
+ }
+ }
+
+ Collections.sort(myData, sDisplayNameComparator);
+
+ return myData;
+ }
+
+ private final static Comparator<Map<String, Object>> sDisplayNameComparator =
+ new Comparator<Map<String, Object>>() {
+ private final Collator collator = Collator.getInstance();
+
+ public int compare(Map<String, Object> map1, Map<String, Object> map2) {
+ return collator.compare(map1.get("title"), map2.get("title"));
+ }
+ };
+
+ protected Intent activityIntent(String pkg, String componentName) {
+ Intent result = new Intent();
+ result.setClassName(pkg, componentName);
+ return result;
+ }
+
+ protected Intent browseIntent(String path) {
+ Intent result = new Intent();
+ result.setClass(this, VectorDrawableTest.class);
+ result.putExtra(EXTRA_PATH, path);
+ return result;
+ }
+
+ protected void addItem(List<Map<String, Object>> data, String name, Intent intent) {
+ Map<String, Object> temp = new HashMap<String, Object>();
+ temp.put("title", name);
+ temp.put("intent", intent);
+ data.add(temp);
+ }
+
+ @Override
+ @SuppressWarnings({ "unchecked", "UnusedParameters" })
+ protected void onListItemClick(ListView l, View v, int position, long id) {
+ Map<String, Object> map = (Map<String, Object>)l.getItemAtPosition(position);
+
+ Intent intent = (Intent) map.get("intent");
+ startActivity(intent);
+ }
+}
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java
new file mode 100644
index 0000000..3430192
--- /dev/null
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorPathChecking.java
@@ -0,0 +1,25 @@
+/*
+ * 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.test.dynamic;
+
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class VectorPathChecking extends VectorDrawablePerformance {
+ {
+ icon = new int[]{
+ R.drawable.vector_test01,
+ R.drawable.vector_test02
+ };
+ }
+}
diff --git a/tests/permission/src/com/android/framework/permission/tests/PmPermissionsTests.java b/tests/permission/src/com/android/framework/permission/tests/PmPermissionsTests.java
index b690c45..93aa555 100644
--- a/tests/permission/src/com/android/framework/permission/tests/PmPermissionsTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/PmPermissionsTests.java
@@ -16,7 +16,7 @@
package com.android.framework.permission.tests;
-import junit.framework.TestCase;
+import android.app.PackageInstallObserver;
import android.content.pm.PackageManager;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -68,10 +68,14 @@
* This test verifies that PackageManger.installPackage enforces permission
* android.permission.INSTALL_PACKAGES
*/
+ private class TestInstallObserver extends PackageInstallObserver {
+ }
+
@SmallTest
public void testInstallPackage() {
+ TestInstallObserver observer = new TestInstallObserver();
try {
- mPm.installPackage(null, null, 0, null);
+ mPm.installPackage(null, observer, 0, null);
fail("PackageManager.installPackage" +
"did not throw SecurityException as expected");
} catch (SecurityException e) {
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index f9a2d19..38bfa00 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -1798,6 +1798,11 @@
return buf;
}
+void* AaptFile::editDataInRange(size_t offset, size_t size)
+{
+ return (void*)(((uint8_t*) editData(offset + size)) + offset);
+}
+
void* AaptFile::editData(size_t* outSize)
{
if (outSize) {
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 336d08b..82dda5f 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -251,6 +251,7 @@
size_t getSize() const { return mDataSize; }
void* editData(size_t size);
void* editData(size_t* outSize = NULL);
+ void* editDataInRange(size_t offset, size_t size);
void* padData(size_t wordSize);
status_t writeData(const void* data, size_t size);
void clearData();
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index 49b8b55..d2eccbe 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -64,6 +64,7 @@
mProduct(NULL), mUseCrunchCache(false), mErrorOnFailedInsert(false),
mErrorOnMissingConfigEntry(false), mOutputTextSymbols(NULL),
mSingleCrunchInputFile(NULL), mSingleCrunchOutputFile(NULL),
+ mBuildSharedLibrary(false),
mArgc(0), mArgv(NULL)
{}
~Bundle(void) {}
@@ -188,6 +189,8 @@
void setSingleCrunchInputFile(const char* val) { mSingleCrunchInputFile = val; }
const char* getSingleCrunchOutputFile() const { return mSingleCrunchOutputFile; }
void setSingleCrunchOutputFile(const char* val) { mSingleCrunchOutputFile = val; }
+ bool getBuildSharedLibrary() const { return mBuildSharedLibrary; }
+ void setBuildSharedLibrary(bool val) { mBuildSharedLibrary = val; }
/*
* Set and get the file specification.
@@ -300,6 +303,7 @@
const char* mOutputTextSymbols;
const char* mSingleCrunchInputFile;
const char* mSingleCrunchOutputFile;
+ bool mBuildSharedLibrary;
/* file specification */
int mArgc;
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 33711fa..1cf4783 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -190,6 +190,9 @@
" Make the resources ID non constant. This is required to make an R java class\n"
" that does not contain the final value but is used to make reusable compiled\n"
" libraries that need to access resources.\n"
+ " --shared-lib\n"
+ " Make a shared library resource package that can be loaded by an application\n"
+ " at runtime to access the libraries resources. Implies --non-constant-id.\n"
" --error-on-failed-insert\n"
" Forces aapt to return an error if it fails to insert values into the manifest\n"
" with --debug-mode, --min-sdk-version, --target-sdk-version --version-code\n"
@@ -618,6 +621,9 @@
bundle.setProduct(argv[0]);
} else if (strcmp(cp, "-non-constant-id") == 0) {
bundle.setNonConstantId(true);
+ } else if (strcmp(cp, "-shared-lib") == 0) {
+ bundle.setNonConstantId(true);
+ bundle.setBuildSharedLibrary(true);
} else if (strcmp(cp, "-no-crunch") == 0) {
bundle.setUseCrunchCache(true);
} else if (strcmp(cp, "-ignore-assets") == 0) {
diff --git a/tools/aapt/ResourceIdCache.cpp b/tools/aapt/ResourceIdCache.cpp
index e03f4f6..d60a07fc 100644
--- a/tools/aapt/ResourceIdCache.cpp
+++ b/tools/aapt/ResourceIdCache.cpp
@@ -98,10 +98,10 @@
void ResourceIdCache::dump() {
printf("ResourceIdCache dump:\n");
- printf("Size: %ld\n", mIdMap.size());
- printf("Hits: %ld\n", mHits);
- printf("Misses: %ld\n", mMisses);
- printf("(Collisions: %ld)\n", mCollisions);
+ printf("Size: %zd\n", mIdMap.size());
+ printf("Hits: %zd\n", mHits);
+ printf("Misses: %zd\n", mMisses);
+ printf("(Collisions: %zd)\n", mCollisions);
}
}
diff --git a/tools/aapt/ResourceIdCache.h b/tools/aapt/ResourceIdCache.h
index e6bcda2..3acdee1 100644
--- a/tools/aapt/ResourceIdCache.h
+++ b/tools/aapt/ResourceIdCache.h
@@ -6,18 +6,20 @@
#ifndef RESOURCE_ID_CACHE_H
#define RESOURCE_ID_CACHE_H
+#include <utils/String16.h>
+
namespace android {
class ResourceIdCache {
public:
- static uint32_t lookup(const android::String16& package,
- const android::String16& type,
- const android::String16& name,
+ static uint32_t lookup(const String16& package,
+ const String16& type,
+ const String16& name,
bool onlyPublic);
- static uint32_t store(const android::String16& package,
- const android::String16& type,
- const android::String16& name,
+ static uint32_t store(const String16& package,
+ const String16& type,
+ const String16& name,
bool onlyPublic,
uint32_t resId);
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 652998e..0fb2606 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -1673,7 +1673,7 @@
ResourceTable::ResourceTable(Bundle* bundle, const String16& assetsPackage)
: mAssetsPackage(assetsPackage), mNextPackageId(1), mHaveAppPackage(false),
- mIsAppPackage(!bundle->getExtending()),
+ mIsAppPackage(!bundle->getExtending()), mIsSharedLibrary(bundle->getBuildSharedLibrary()),
mNumLocal(0),
mBundle(bundle)
{
@@ -1695,8 +1695,9 @@
const size_t N = incl.getBasePackageCount();
for (size_t phase=0; phase<2; phase++) {
for (size_t i=0; i<N; i++) {
- String16 name(incl.getBasePackageName(i));
+ const String16 name = incl.getBasePackageName(i);
uint32_t id = incl.getBasePackageId(i);
+
// First time through: only add base packages (id
// is not 0); second time through add the other
// packages.
@@ -1722,7 +1723,7 @@
}
}
if (id != 0) {
- NOISY(printf("Including package %s with ID=%d\n",
+ NOISY(fprintf(stderr, "Including package %s with ID=%d\n",
String8(name).string(), id));
sp<Package> p = new Package(name, id);
mPackages.add(name, p);
@@ -2687,6 +2688,9 @@
bool useUTF8 = !bundle->getUTF16StringsOption();
+ // The libraries this table references.
+ Vector<sp<Package> > libraryPackages;
+
// Iterate through all data, collecting all values (strings,
// references, etc).
StringPool valueStrings(useUTF8);
@@ -2694,8 +2698,22 @@
for (pi=0; pi<N; pi++) {
sp<Package> p = mOrderedPackages.itemAt(pi);
if (p->getTypes().size() == 0) {
- // Empty, skip!
+ // Empty, this is an imported package being used as
+ // a shared library. We do not flatten this package.
+ if (p->getAssignedId() != 0x01 && p->getName() != String16("android")) {
+ // This is not the base Android package, and it is a library
+ // so we must add a reference to the library when flattening.
+ libraryPackages.add(p);
+ }
continue;
+ } else if (p->getAssignedId() == 0x00) {
+ if (!bundle->getBuildSharedLibrary()) {
+ fprintf(stderr, "ERROR: Package %s can not have ID=0x00 unless building a shared library.",
+ String8(p->getName()).string());
+ return UNKNOWN_ERROR;
+ }
+ // If this is a shared library, we also include ourselves as an entry.
+ libraryPackages.add(p);
}
StringPool typeStrings(useUTF8);
@@ -2778,7 +2796,7 @@
}
ssize_t strAmt = 0;
-
+
// Now build the array of package chunks.
Vector<sp<AaptFile> > flatPackages;
for (pi=0; pi<N; pi++) {
@@ -2827,6 +2845,12 @@
return amt;
}
+ err = flattenLibraryTable(data, libraryPackages);
+ if (err != NO_ERROR) {
+ fprintf(stderr, "ERROR: failed to write library table\n");
+ return err;
+ }
+
// Build the type chunks inside of this package.
for (size_t ti=0; ti<N; ti++) {
// Retrieve them in the same order as the type string block.
@@ -3053,7 +3077,7 @@
fprintf(stderr, "**** value strings: %d\n", amt);
fprintf(stderr, "**** total strings: %d\n", strAmt);
#endif
-
+
for (pi=0; pi<flatPackages.size(); pi++) {
err = dest->writeData(flatPackages[pi]->getData(),
flatPackages[pi]->getSize());
@@ -3078,6 +3102,38 @@
return NO_ERROR;
}
+status_t ResourceTable::flattenLibraryTable(const sp<AaptFile>& dest, const Vector<sp<Package> >& libs) {
+ // Write out the library table if necessary
+ if (libs.size() > 0) {
+ NOISY(fprintf(stderr, "Writing library reference table\n"));
+
+ const size_t libStart = dest->getSize();
+ const size_t count = libs.size();
+ ResTable_lib_header* libHeader = (ResTable_lib_header*) dest->editDataInRange(libStart, sizeof(ResTable_lib_header));
+
+ memset(libHeader, 0, sizeof(*libHeader));
+ libHeader->header.type = htods(RES_TABLE_LIBRARY_TYPE);
+ libHeader->header.headerSize = htods(sizeof(*libHeader));
+ libHeader->header.size = htodl(sizeof(*libHeader) + (sizeof(ResTable_lib_entry) * count));
+ libHeader->count = htodl(count);
+
+ // Write the library entries
+ for (size_t i = 0; i < count; i++) {
+ const size_t entryStart = dest->getSize();
+ sp<Package> libPackage = libs[i];
+ NOISY(fprintf(stderr, " Entry %s -> 0x%02x\n",
+ String8(libPackage->getName()).string(),
+ (uint8_t)libPackage->getAssignedId()));
+
+ ResTable_lib_entry* entry = (ResTable_lib_entry*) dest->editDataInRange(entryStart, sizeof(ResTable_lib_entry));
+ memset(entry, 0, sizeof(*entry));
+ entry->packageId = htodl(libPackage->getAssignedId());
+ strcpy16_htod(entry->packageName, libPackage->getName().string());
+ }
+ }
+ return NO_ERROR;
+}
+
void ResourceTable::writePublicDefinitions(const String16& package, FILE* fp)
{
fprintf(fp,
@@ -3847,7 +3903,7 @@
return NULL;
}
mHaveAppPackage = true;
- p = new Package(package, 127);
+ p = new Package(package, mIsSharedLibrary ? 0 : 127);
} else {
p = new Package(package, mNextPackageId);
}
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index 75005cd..ec8fd175e 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -224,6 +224,7 @@
status_t validateLocalizations(void);
status_t flatten(Bundle*, const sp<AaptFile>& dest);
+ status_t flattenLibraryTable(const sp<AaptFile>& dest, const Vector<sp<Package> >& libs);
void writePublicDefinitions(const String16& package, FILE* fp);
@@ -546,6 +547,7 @@
uint32_t mNextPackageId;
bool mHaveAppPackage;
bool mIsAppPackage;
+ bool mIsSharedLibrary;
size_t mNumLocal;
SourcePos mCurrentXmlPos;
Bundle* mBundle;
diff --git a/tools/aapt/printapk.cpp b/tools/aapt/printapk.cpp
index 4cf73d8..def6e2e 100644
--- a/tools/aapt/printapk.cpp
+++ b/tools/aapt/printapk.cpp
@@ -115,8 +115,8 @@
size_t basePackageCount = res.getBasePackageCount();
printf("Base Packages: %d\n", (int)basePackageCount);
for (size_t bpIndex=0; bpIndex<basePackageCount; bpIndex++) {
- const char16_t* ch = res.getBasePackageName(bpIndex);
- String8 s = String8(String16(ch));
+ const String16 ch = res.getBasePackageName(bpIndex);
+ String8 s = String8(ch);
printf(" [%3d] %s\n", (int)bpIndex, s.string());
}
#endif
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index 1fa9615..cb68340 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -53,6 +53,7 @@
$(LOCAL_BUILT_MODULE): $(built_core_dep) \
$(built_framework_dep) \
$(built_ext_dep) \
+ $(built_ext_data) \
$(built_layoutlib_create_jar)
$(hide) echo "host layoutlib_create: $@"
$(hide) mkdir -p $(dir $@)
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index cfe7525..cc621c4 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -52,9 +52,9 @@
private final BridgeContext mContext;
private final boolean mPlatformFile;
- private ResourceValue[] mResourceData;
- private String[] mNames;
- private boolean[] mIsFramework;
+ private final ResourceValue[] mResourceData;
+ private final String[] mNames;
+ private final boolean[] mIsFramework;
public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len,
boolean platformFile) {
@@ -81,8 +81,8 @@
}
/**
- * Seals the array after all calls to {@link #bridgeSetValue(int, String, ResourceValue)} have
- * been done.
+ * Seals the array after all calls to
+ * {@link #bridgeSetValue(int, String, boolean, ResourceValue)} have been done.
* <p/>This allows to compute the list of non default values, permitting
* {@link #getIndexCount()} to return the proper value.
*/
@@ -252,7 +252,7 @@
for (String keyword : keywords) {
Integer i = map.get(keyword.trim());
if (i != null) {
- result |= i.intValue();
+ result |= i;
} else {
Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
String.format(
@@ -731,7 +731,7 @@
}
// not a direct id valid reference? resolve it
- Integer idValue = null;
+ Integer idValue;
if (resValue.isFramework()) {
idValue = Bridge.getResourceId(resValue.getResourceType(),
@@ -742,7 +742,7 @@
}
if (idValue != null) {
- return idValue.intValue();
+ return idValue;
}
Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
@@ -753,6 +753,12 @@
return defValue;
}
+ @Override
+ public int getThemeAttributeId(int index, int defValue) {
+ // TODO: Get the right Theme Attribute ID to enable caching of the drawables.
+ return defValue;
+ }
+
/**
* Retrieve the Drawable for the attribute at <var>index</var>. This
* gets the resource ID of the selected attribute, and uses
@@ -854,6 +860,7 @@
*/
@Override
public boolean hasValue(int index) {
+ //noinspection SimplifiableIfStatement
if (index < 0 || index >= mResourceData.length) {
return false;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java
index 53e1640..a2a8aa9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java
@@ -18,6 +18,7 @@
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.GrowingArrayUtils;
import android.util.SparseArray;
@@ -59,10 +60,8 @@
* number of mappings.
*/
public SparseWeakArray(int initialCapacity) {
- initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity);
-
- mKeys = new long[initialCapacity];
- mValues = new WeakReference[initialCapacity];
+ mKeys = ArrayUtils.newUnpaddedLongArray(initialCapacity);
+ mValues = new WeakReference[mKeys.length];
mSize = 0;
}
@@ -142,18 +141,6 @@
mGarbage = false;
mSize = o;
-
- int newSize = ArrayUtils.idealLongArraySize(mSize);
- if (newSize < mKeys.length) {
- long[] nkeys = new long[newSize];
- WeakReference<?>[] nvalues = new WeakReference[newSize];
-
- System.arraycopy(mKeys, 0, nkeys, 0, newSize);
- System.arraycopy(mValues, 0, nvalues, 0, newSize);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
}
/**
@@ -182,28 +169,8 @@
i = ~binarySearch(mKeys, 0, mSize, key);
}
- if (mSize >= mKeys.length) {
- int n = ArrayUtils.idealLongArraySize(mSize + 1);
-
- long[] nkeys = new long[n];
- WeakReference<?>[] nvalues = new WeakReference[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- if (mSize - i != 0) {
- // Log.e("SparseArray", "move " + (mSize - i));
- System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
- System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
- }
-
- mKeys[i] = key;
- mValues[i] = new WeakReference(value);
+ mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
+ mValues = GrowingArrayUtils.insert(mValues, mSize, i, new WeakReference(value));
mSize++;
}
}
@@ -321,24 +288,9 @@
gc();
}
- int pos = mSize;
- if (pos >= mKeys.length) {
- int n = ArrayUtils.idealLongArraySize(pos + 1);
-
- long[] nkeys = new long[n];
- WeakReference<?>[] nvalues = new WeakReference[n];
-
- // Log.e("SparseArray", "grow " + mKeys.length + " to " + n);
- System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
- System.arraycopy(mValues, 0, nvalues, 0, mValues.length);
-
- mKeys = nkeys;
- mValues = nvalues;
- }
-
- mKeys[pos] = key;
- mValues[pos] = new WeakReference(value);
- mSize = pos + 1;
+ mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
+ mValues = GrowingArrayUtils.append(mValues, mSize, new WeakReference(value));
+ mSize++;
}
private boolean hasReclaimedRefs() {
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
index 9a31705..3e75c9e 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
@@ -632,8 +632,8 @@
// field instruction
@Override
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
- // name is the field's name.
- considerName(name);
+ // owner is the class that declares the field.
+ considerName(owner);
// desc is the field's descriptor (see Type).
considerDesc(desc);
}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java
index c988c70..2016c0e 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java
@@ -527,7 +527,8 @@
// field instruction
@Override
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
- // name is the field's name.
+ // owner is the class that declares the field.
+ considerName(owner);
// desc is the field's descriptor (see Type).
considerDesc(desc);
}
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java
index 7ec0d38..78e2c48 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java
@@ -83,6 +83,7 @@
"mock_android.dummy.InnerTest$MyStaticInnerClass",
"mock_android.dummy.InnerTest$NotStaticInner1",
"mock_android.dummy.InnerTest$NotStaticInner2",
+ "mock_android.util.EmptyArray",
"mock_android.view.View",
"mock_android.view.ViewGroup",
"mock_android.view.ViewGroup$LayoutParams",
@@ -217,15 +218,16 @@
TreeMap<String, ClassReader> in_deps = new TreeMap<String, ClassReader>();
TreeMap<String, ClassReader> out_deps = new TreeMap<String, ClassReader>();
- ClassReader cr = mAa.findClass("mock_android.widget.TableLayout", zipClasses, keep);
+ ClassReader cr = mAa.findClass("mock_android.widget.LinearLayout", zipClasses, keep);
DependencyVisitor visitor = mAa.getVisitor(zipClasses, keep, new_keep, in_deps, out_deps);
// get first level dependencies
cr.accept(visitor, 0 /* flags */);
assertArrayEquals(new String[] {
+ "mock_android.util.EmptyArray",
"mock_android.view.ViewGroup",
- "mock_android.widget.TableLayout$LayoutParams",
+ "mock_android.widget.LinearLayout$LayoutParams",
},
out_deps.keySet().toArray());
@@ -255,7 +257,7 @@
assertArrayEquals(new String[] { }, out_deps.keySet().toArray());
assertArrayEquals(new String[] {
- "mock_android.widget.TableLayout",
+ "mock_android.widget.LinearLayout",
}, keep.keySet().toArray());
}
}
diff --git a/tools/layoutlib/create/tests/data/mock_android.jar b/tools/layoutlib/create/tests/data/mock_android.jar
index 8dd0481..c6ca3c4 100644
--- a/tools/layoutlib/create/tests/data/mock_android.jar
+++ b/tools/layoutlib/create/tests/data/mock_android.jar
Binary files differ
diff --git a/tools/layoutlib/create/tests/mock_data/mock_android/util/EmptyArray.java b/tools/layoutlib/create/tests/mock_data/mock_android/util/EmptyArray.java
new file mode 100644
index 0000000..aaeebf6
--- /dev/null
+++ b/tools/layoutlib/create/tests/mock_data/mock_android/util/EmptyArray.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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 mock_android.util;
+
+import java.lang.JavaClass;
+
+public class EmptyArray {
+
+ public static final Object[] OBJECT = new Object[0];
+}
diff --git a/tools/layoutlib/create/tests/mock_data/mock_android/widget/LinearLayout.java b/tools/layoutlib/create/tests/mock_data/mock_android/widget/LinearLayout.java
index 3870a63..af56c4b 100644
--- a/tools/layoutlib/create/tests/mock_data/mock_android/widget/LinearLayout.java
+++ b/tools/layoutlib/create/tests/mock_data/mock_android/widget/LinearLayout.java
@@ -16,11 +16,13 @@
package mock_android.widget;
+import mock_android.util.EmptyArray;
import mock_android.view.ViewGroup;
public class LinearLayout extends ViewGroup {
- public class LayoutParams extends mock_android.view.ViewGroup.LayoutParams {
+ Object[] mObjects = EmptyArray.OBJECT;
+ public class LayoutParams extends MarginLayoutParams {
}
diff --git a/wifi/java/android/net/wifi/BatchedScanSettings.java b/wifi/java/android/net/wifi/BatchedScanSettings.java
index f7ebc17..54801ad 100644
--- a/wifi/java/android/net/wifi/BatchedScanSettings.java
+++ b/wifi/java/android/net/wifi/BatchedScanSettings.java
@@ -34,17 +34,17 @@
/** Used to indicate no preference for an int value */
public final static int UNSPECIFIED = Integer.MAX_VALUE;
- // TODO - make MIN/mAX dynamic and gservices adjustable.
+ // TODO - make MIN/mAX as standard for wifi batch capability requirement.
public final static int MIN_SCANS_PER_BATCH = 2;
- public final static int MAX_SCANS_PER_BATCH = 255;
+ public final static int MAX_SCANS_PER_BATCH = 20;
public final static int DEFAULT_SCANS_PER_BATCH = MAX_SCANS_PER_BATCH;
public final static int MIN_AP_PER_SCAN = 2;
- public final static int MAX_AP_PER_SCAN = 255;
+ public final static int MAX_AP_PER_SCAN = 16;
public final static int DEFAULT_AP_PER_SCAN = 16;
- public final static int MIN_INTERVAL_SEC = 0;
- public final static int MAX_INTERVAL_SEC = 3600;
+ public final static int MIN_INTERVAL_SEC = 10;
+ public final static int MAX_INTERVAL_SEC = 500;
public final static int DEFAULT_INTERVAL_SEC = 30;
public final static int MIN_AP_FOR_DISTANCE = 0;
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 12729d2..d7ecaff 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -40,8 +40,7 @@
*/
public String capabilities;
/**
- * The detected signal level in dBm. At least those are the units used by
- * the TI driver.
+ * The detected signal level in dBm.
*/
public int level;
/**
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 4a6821c..f44cb0a 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -157,9 +157,8 @@
/**
* Returns the received signal strength indicator of the current 802.11
- * network.
- * <p><strong>This is not normalized, but should be!</strong></p>
- * @return the RSSI, in the range ??? to ???
+ * network, in dBm.
+ * @return the RSSI, in the range -110 to 10
*/
public int getRssi() {
return mRssi;
diff --git a/core/java/android/view/DisplayList.java b/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
similarity index 64%
copy from core/java/android/view/DisplayList.java
copy to wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
index ed52803..2b1601b 100644
--- a/core/java/android/view/DisplayList.java
+++ b/wifi/java/android/net/wifi/hotspot/IWifiHotspotManager.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
+/**
+ * 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
+ * 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,
@@ -14,12 +14,15 @@
* limitations under the License.
*/
-package android.view;
+package android.net.wifi.hotspot;
-/** TODO: Remove once frameworks/webview is updated
- * @hide
+/**
+ * Interface that allows controlling and querying Hotspot connectivity.
+ *
+ * {@hide}
*/
-public class DisplayList {
- /** @hide */
- public static final int STATUS_DONE = 0x0;
+interface IWifiHotspotManager
+{
+ void test();
}
+
diff --git a/wifi/java/android/net/wifi/hotspot/WifiHotspotManager.java b/wifi/java/android/net/wifi/hotspot/WifiHotspotManager.java
new file mode 100644
index 0000000..ac15017
--- /dev/null
+++ b/wifi/java/android/net/wifi/hotspot/WifiHotspotManager.java
@@ -0,0 +1,48 @@
+/*
+ * 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.net.wifi.hotspot;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * TODO: doc
+ */
+public class WifiHotspotManager {
+
+ private static final String TAG = "WifiHotspotManager";
+
+ private Context mContext;
+ IWifiHotspotManager mService;
+
+ public WifiHotspotManager(Context context, IWifiHotspotManager service) {
+ mContext = context;
+ mService = service;
+ }
+
+ public void test() {
+ try{
+ Log.d(TAG, "test()");
+ mService.test();
+ }
+ catch (RemoteException e) {
+ Log.e(TAG, "test() exception");
+ e.printStackTrace();
+ }
+ }
+}