Merge "Refactored the notification animations, improved stack scroller"
diff --git a/Android.mk b/Android.mk
index 966c64d..c80a9ab 100644
--- a/Android.mk
+++ b/Android.mk
@@ -78,7 +78,6 @@
core/java/android/app/IStopUserCallback.aidl \
core/java/android/app/task/ITaskCallback.aidl \
core/java/android/app/task/ITaskService.aidl \
- core/java/android/app/IThumbnailReceiver.aidl \
core/java/android/app/IThumbnailRetriever.aidl \
core/java/android/app/ITransientNotification.aidl \
core/java/android/app/IUiAutomationConnection.aidl \
@@ -157,6 +156,7 @@
core/java/android/net/INetworkManagementEventObserver.aidl \
core/java/android/net/INetworkPolicyListener.aidl \
core/java/android/net/INetworkPolicyManager.aidl \
+ core/java/android/net/INetworkScoreCache.aidl \
core/java/android/net/INetworkScoreService.aidl \
core/java/android/net/INetworkStatsService.aidl \
core/java/android/net/INetworkStatsSession.aidl \
@@ -199,6 +199,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/fingerprint/IFingerprintService.aidl \
+ core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl \
core/java/android/service/trust/ITrustAgentService.aidl \
core/java/android/service/trust/ITrustAgentServiceCallback.aidl \
core/java/android/service/voice/IVoiceInteractionService.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index c6f6a62..c841338 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -190,6 +190,7 @@
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/view/IMagnificationCallbacks*)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/tv/)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/media/java/android/media/)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/app)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/api/current.txt b/api/current.txt
index 71dc9f6..a45ddce 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -267,6 +267,7 @@
field public static final int actionModeSplitBackground = 16843677; // 0x101039d
field public static final int actionModeStyle = 16843668; // 0x1010394
field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
+ field public static final int actionOverflowMenuStyle = 16843857; // 0x1010451
field public static final int actionProviderClass = 16843657; // 0x1010389
field public static final int actionViewClass = 16843516; // 0x10102fc
field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
@@ -1858,28 +1859,28 @@
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 = 16974352; // 0x1030210
- field public static final int TextAppearance_Quantum_Body1 = 16974546; // 0x10302d2
- field public static final int TextAppearance_Quantum_Body2 = 16974545; // 0x10302d1
- field public static final int TextAppearance_Quantum_Button = 16974549; // 0x10302d5
- field public static final int TextAppearance_Quantum_Caption = 16974547; // 0x10302d3
+ field public static final int TextAppearance_Quantum_Body1 = 16974544; // 0x10302d0
+ field public static final int TextAppearance_Quantum_Body2 = 16974543; // 0x10302cf
+ field public static final int TextAppearance_Quantum_Button = 16974547; // 0x10302d3
+ field public static final int TextAppearance_Quantum_Caption = 16974545; // 0x10302d1
field public static final int TextAppearance_Quantum_DialogWindowTitle = 16974353; // 0x1030211
- field public static final int TextAppearance_Quantum_Display1 = 16974541; // 0x10302cd
- field public static final int TextAppearance_Quantum_Display2 = 16974540; // 0x10302cc
- field public static final int TextAppearance_Quantum_Display3 = 16974539; // 0x10302cb
- field public static final int TextAppearance_Quantum_Display4 = 16974538; // 0x10302ca
- field public static final int TextAppearance_Quantum_Headline = 16974542; // 0x10302ce
+ field public static final int TextAppearance_Quantum_Display1 = 16974539; // 0x10302cb
+ field public static final int TextAppearance_Quantum_Display2 = 16974538; // 0x10302ca
+ field public static final int TextAppearance_Quantum_Display3 = 16974537; // 0x10302c9
+ field public static final int TextAppearance_Quantum_Display4 = 16974536; // 0x10302c8
+ field public static final int TextAppearance_Quantum_Headline = 16974540; // 0x10302cc
field public static final int TextAppearance_Quantum_Inverse = 16974354; // 0x1030212
field public static final int TextAppearance_Quantum_Large = 16974355; // 0x1030213
field public static final int TextAppearance_Quantum_Large_Inverse = 16974356; // 0x1030214
field public static final int TextAppearance_Quantum_Medium = 16974357; // 0x1030215
field public static final int TextAppearance_Quantum_Medium_Inverse = 16974358; // 0x1030216
- field public static final int TextAppearance_Quantum_Menu = 16974548; // 0x10302d4
+ field public static final int TextAppearance_Quantum_Menu = 16974546; // 0x10302d2
field public static final int TextAppearance_Quantum_SearchResult_Subtitle = 16974359; // 0x1030217
field public static final int TextAppearance_Quantum_SearchResult_Title = 16974360; // 0x1030218
field public static final int TextAppearance_Quantum_Small = 16974361; // 0x1030219
field public static final int TextAppearance_Quantum_Small_Inverse = 16974362; // 0x103021a
- field public static final int TextAppearance_Quantum_Subhead = 16974544; // 0x10302d0
- field public static final int TextAppearance_Quantum_Title = 16974543; // 0x10302cf
+ field public static final int TextAppearance_Quantum_Subhead = 16974542; // 0x10302ce
+ field public static final int TextAppearance_Quantum_Title = 16974541; // 0x10302cd
field public static final int TextAppearance_Quantum_Widget = 16974364; // 0x103021c
field public static final int TextAppearance_Quantum_Widget_ActionBar_Menu = 16974365; // 0x103021d
field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle = 16974366; // 0x103021e
@@ -2329,118 +2330,116 @@
field public static final int Widget_Quantum_ActionMode = 16974423; // 0x1030257
field public static final int Widget_Quantum_AutoCompleteTextView = 16974424; // 0x1030258
field public static final int Widget_Quantum_Button = 16974425; // 0x1030259
- field public static final int Widget_Quantum_ButtonBar = 16974433; // 0x1030261
- field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974434; // 0x1030262
+ field public static final int Widget_Quantum_ButtonBar = 16974431; // 0x103025f
+ field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974432; // 0x1030260
field public static final int Widget_Quantum_Button_Borderless = 16974426; // 0x103025a
field public static final int Widget_Quantum_Button_Borderless_Small = 16974427; // 0x103025b
field public static final int Widget_Quantum_Button_Inset = 16974428; // 0x103025c
- field public static final int Widget_Quantum_Button_Paper = 16974431; // 0x103025f
- field public static final int Widget_Quantum_Button_Paper_Color = 16974432; // 0x1030260
field public static final int Widget_Quantum_Button_Small = 16974429; // 0x103025d
field public static final int Widget_Quantum_Button_Toggle = 16974430; // 0x103025e
- field public static final int Widget_Quantum_CalendarView = 16974435; // 0x1030263
- field public static final int Widget_Quantum_CheckedTextView = 16974436; // 0x1030264
- field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974437; // 0x1030265
- field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974438; // 0x1030266
- field public static final int Widget_Quantum_CompoundButton_Star = 16974439; // 0x1030267
- field public static final int Widget_Quantum_DatePicker = 16974440; // 0x1030268
- field public static final int Widget_Quantum_DropDownItem = 16974441; // 0x1030269
- field public static final int Widget_Quantum_DropDownItem_Spinner = 16974442; // 0x103026a
- field public static final int Widget_Quantum_EditText = 16974443; // 0x103026b
- field public static final int Widget_Quantum_ExpandableListView = 16974444; // 0x103026c
- field public static final int Widget_Quantum_FastScroll = 16974445; // 0x103026d
- field public static final int Widget_Quantum_FragmentBreadCrumbs = 16974446; // 0x103026e
- field public static final int Widget_Quantum_GridView = 16974447; // 0x103026f
- field public static final int Widget_Quantum_HorizontalScrollView = 16974448; // 0x1030270
- field public static final int Widget_Quantum_ImageButton = 16974449; // 0x1030271
- field public static final int Widget_Quantum_Light = 16974475; // 0x103028b
- field public static final int Widget_Quantum_Light_ActionBar = 16974476; // 0x103028c
- field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974477; // 0x103028d
- field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974478; // 0x103028e
- field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974479; // 0x103028f
- field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974480; // 0x1030290
- field public static final int Widget_Quantum_Light_ActionButton = 16974481; // 0x1030291
- field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974482; // 0x1030292
- field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974483; // 0x1030293
- field public static final int Widget_Quantum_Light_ActionMode = 16974484; // 0x1030294
- field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974485; // 0x1030295
- field public static final int Widget_Quantum_Light_Button = 16974486; // 0x1030296
- field public static final int Widget_Quantum_Light_ButtonBar = 16974494; // 0x103029e
- field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974495; // 0x103029f
- field public static final int Widget_Quantum_Light_Button_Borderless = 16974487; // 0x1030297
- field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974488; // 0x1030298
- field public static final int Widget_Quantum_Light_Button_Inset = 16974489; // 0x1030299
- field public static final int Widget_Quantum_Light_Button_Paper = 16974492; // 0x103029c
- field public static final int Widget_Quantum_Light_Button_Paper_Color = 16974493; // 0x103029d
- field public static final int Widget_Quantum_Light_Button_Small = 16974490; // 0x103029a
- field public static final int Widget_Quantum_Light_Button_Toggle = 16974491; // 0x103029b
- field public static final int Widget_Quantum_Light_CalendarView = 16974496; // 0x10302a0
- field public static final int Widget_Quantum_Light_CheckedTextView = 16974497; // 0x10302a1
- field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974498; // 0x10302a2
- field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974499; // 0x10302a3
- field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974500; // 0x10302a4
- field public static final int Widget_Quantum_Light_DropDownItem = 16974501; // 0x10302a5
- field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974502; // 0x10302a6
- field public static final int Widget_Quantum_Light_EditText = 16974503; // 0x10302a7
- field public static final int Widget_Quantum_Light_ExpandableListView = 16974504; // 0x10302a8
- field public static final int Widget_Quantum_Light_FastScroll = 16974505; // 0x10302a9
- field public static final int Widget_Quantum_Light_FragmentBreadCrumbs = 16974506; // 0x10302aa
- field public static final int Widget_Quantum_Light_GridView = 16974507; // 0x10302ab
- field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974508; // 0x10302ac
- field public static final int Widget_Quantum_Light_ImageButton = 16974509; // 0x10302ad
- field public static final int Widget_Quantum_Light_ListPopupWindow = 16974510; // 0x10302ae
- field public static final int Widget_Quantum_Light_ListView = 16974511; // 0x10302af
- field public static final int Widget_Quantum_Light_ListView_DropDown = 16974512; // 0x10302b0
- field public static final int Widget_Quantum_Light_MediaRouteButton = 16974513; // 0x10302b1
- field public static final int Widget_Quantum_Light_PopupMenu = 16974514; // 0x10302b2
- field public static final int Widget_Quantum_Light_PopupWindow = 16974515; // 0x10302b3
- field public static final int Widget_Quantum_Light_ProgressBar = 16974516; // 0x10302b4
- field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974517; // 0x10302b5
- field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974518; // 0x10302b6
- field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974519; // 0x10302b7
- field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974520; // 0x10302b8
- field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974521; // 0x10302b9
- field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974522; // 0x10302ba
- field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974523; // 0x10302bb
- field public static final int Widget_Quantum_Light_RatingBar = 16974524; // 0x10302bc
- field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974525; // 0x10302bd
- field public static final int Widget_Quantum_Light_RatingBar_Small = 16974526; // 0x10302be
- field public static final int Widget_Quantum_Light_ScrollView = 16974527; // 0x10302bf
- field public static final int Widget_Quantum_Light_SeekBar = 16974528; // 0x10302c0
- field public static final int Widget_Quantum_Light_SegmentedButton = 16974529; // 0x10302c1
- field public static final int Widget_Quantum_Light_Spinner = 16974531; // 0x10302c3
- field public static final int Widget_Quantum_Light_StackView = 16974530; // 0x10302c2
- field public static final int Widget_Quantum_Light_Tab = 16974532; // 0x10302c4
- field public static final int Widget_Quantum_Light_TabWidget = 16974533; // 0x10302c5
- field public static final int Widget_Quantum_Light_TextView = 16974534; // 0x10302c6
- field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974535; // 0x10302c7
- field public static final int Widget_Quantum_Light_WebTextView = 16974536; // 0x10302c8
- field public static final int Widget_Quantum_Light_WebView = 16974537; // 0x10302c9
- field public static final int Widget_Quantum_ListPopupWindow = 16974450; // 0x1030272
- field public static final int Widget_Quantum_ListView = 16974451; // 0x1030273
- field public static final int Widget_Quantum_ListView_DropDown = 16974452; // 0x1030274
- field public static final int Widget_Quantum_MediaRouteButton = 16974453; // 0x1030275
- field public static final int Widget_Quantum_PopupMenu = 16974454; // 0x1030276
- field public static final int Widget_Quantum_PopupWindow = 16974455; // 0x1030277
- field public static final int Widget_Quantum_ProgressBar = 16974456; // 0x1030278
- field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974457; // 0x1030279
- field public static final int Widget_Quantum_ProgressBar_Large = 16974458; // 0x103027a
- field public static final int Widget_Quantum_ProgressBar_Small = 16974459; // 0x103027b
- field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974460; // 0x103027c
- field public static final int Widget_Quantum_RatingBar = 16974461; // 0x103027d
- field public static final int Widget_Quantum_RatingBar_Indicator = 16974462; // 0x103027e
- field public static final int Widget_Quantum_RatingBar_Small = 16974463; // 0x103027f
- field public static final int Widget_Quantum_ScrollView = 16974464; // 0x1030280
- field public static final int Widget_Quantum_SeekBar = 16974465; // 0x1030281
- field public static final int Widget_Quantum_SegmentedButton = 16974466; // 0x1030282
- field public static final int Widget_Quantum_Spinner = 16974468; // 0x1030284
- field public static final int Widget_Quantum_StackView = 16974467; // 0x1030283
- field public static final int Widget_Quantum_Tab = 16974469; // 0x1030285
- field public static final int Widget_Quantum_TabWidget = 16974470; // 0x1030286
- field public static final int Widget_Quantum_TextView = 16974471; // 0x1030287
- field public static final int Widget_Quantum_TextView_SpinnerItem = 16974472; // 0x1030288
- field public static final int Widget_Quantum_WebTextView = 16974473; // 0x1030289
- field public static final int Widget_Quantum_WebView = 16974474; // 0x103028a
+ field public static final int Widget_Quantum_CalendarView = 16974433; // 0x1030261
+ field public static final int Widget_Quantum_CheckedTextView = 16974434; // 0x1030262
+ field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974435; // 0x1030263
+ field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974436; // 0x1030264
+ field public static final int Widget_Quantum_CompoundButton_Star = 16974437; // 0x1030265
+ field public static final int Widget_Quantum_DatePicker = 16974438; // 0x1030266
+ field public static final int Widget_Quantum_DropDownItem = 16974439; // 0x1030267
+ field public static final int Widget_Quantum_DropDownItem_Spinner = 16974440; // 0x1030268
+ field public static final int Widget_Quantum_EditText = 16974441; // 0x1030269
+ field public static final int Widget_Quantum_ExpandableListView = 16974442; // 0x103026a
+ field public static final int Widget_Quantum_FastScroll = 16974443; // 0x103026b
+ field public static final int Widget_Quantum_FragmentBreadCrumbs = 16974444; // 0x103026c
+ field public static final int Widget_Quantum_GridView = 16974445; // 0x103026d
+ field public static final int Widget_Quantum_HorizontalScrollView = 16974446; // 0x103026e
+ field public static final int Widget_Quantum_ImageButton = 16974447; // 0x103026f
+ field public static final int Widget_Quantum_Light = 16974474; // 0x103028a
+ field public static final int Widget_Quantum_Light_ActionBar = 16974475; // 0x103028b
+ field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974476; // 0x103028c
+ field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974477; // 0x103028d
+ field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974478; // 0x103028e
+ field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974479; // 0x103028f
+ field public static final int Widget_Quantum_Light_ActionButton = 16974480; // 0x1030290
+ field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974481; // 0x1030291
+ field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974482; // 0x1030292
+ field public static final int Widget_Quantum_Light_ActionMode = 16974483; // 0x1030293
+ field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974484; // 0x1030294
+ field public static final int Widget_Quantum_Light_Button = 16974485; // 0x1030295
+ field public static final int Widget_Quantum_Light_ButtonBar = 16974491; // 0x103029b
+ field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974492; // 0x103029c
+ field public static final int Widget_Quantum_Light_Button_Borderless = 16974486; // 0x1030296
+ field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974487; // 0x1030297
+ field public static final int Widget_Quantum_Light_Button_Inset = 16974488; // 0x1030298
+ field public static final int Widget_Quantum_Light_Button_Small = 16974489; // 0x1030299
+ field public static final int Widget_Quantum_Light_Button_Toggle = 16974490; // 0x103029a
+ field public static final int Widget_Quantum_Light_CalendarView = 16974493; // 0x103029d
+ field public static final int Widget_Quantum_Light_CheckedTextView = 16974494; // 0x103029e
+ field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974495; // 0x103029f
+ field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974496; // 0x10302a0
+ field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974497; // 0x10302a1
+ field public static final int Widget_Quantum_Light_DropDownItem = 16974498; // 0x10302a2
+ field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974499; // 0x10302a3
+ field public static final int Widget_Quantum_Light_EditText = 16974500; // 0x10302a4
+ field public static final int Widget_Quantum_Light_ExpandableListView = 16974501; // 0x10302a5
+ field public static final int Widget_Quantum_Light_FastScroll = 16974502; // 0x10302a6
+ field public static final int Widget_Quantum_Light_FragmentBreadCrumbs = 16974503; // 0x10302a7
+ field public static final int Widget_Quantum_Light_GridView = 16974504; // 0x10302a8
+ field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974505; // 0x10302a9
+ field public static final int Widget_Quantum_Light_ImageButton = 16974506; // 0x10302aa
+ field public static final int Widget_Quantum_Light_ListPopupWindow = 16974507; // 0x10302ab
+ field public static final int Widget_Quantum_Light_ListView = 16974508; // 0x10302ac
+ field public static final int Widget_Quantum_Light_ListView_DropDown = 16974509; // 0x10302ad
+ field public static final int Widget_Quantum_Light_MediaRouteButton = 16974510; // 0x10302ae
+ field public static final int Widget_Quantum_Light_PopupMenu = 16974511; // 0x10302af
+ field public static final int Widget_Quantum_Light_PopupMenu_Overflow = 16974512; // 0x10302b0
+ field public static final int Widget_Quantum_Light_PopupWindow = 16974513; // 0x10302b1
+ field public static final int Widget_Quantum_Light_ProgressBar = 16974514; // 0x10302b2
+ field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974515; // 0x10302b3
+ field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974516; // 0x10302b4
+ field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974517; // 0x10302b5
+ field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974518; // 0x10302b6
+ field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974519; // 0x10302b7
+ field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974520; // 0x10302b8
+ field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974521; // 0x10302b9
+ field public static final int Widget_Quantum_Light_RatingBar = 16974522; // 0x10302ba
+ field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974523; // 0x10302bb
+ field public static final int Widget_Quantum_Light_RatingBar_Small = 16974524; // 0x10302bc
+ field public static final int Widget_Quantum_Light_ScrollView = 16974525; // 0x10302bd
+ field public static final int Widget_Quantum_Light_SeekBar = 16974526; // 0x10302be
+ field public static final int Widget_Quantum_Light_SegmentedButton = 16974527; // 0x10302bf
+ field public static final int Widget_Quantum_Light_Spinner = 16974529; // 0x10302c1
+ field public static final int Widget_Quantum_Light_StackView = 16974528; // 0x10302c0
+ field public static final int Widget_Quantum_Light_Tab = 16974530; // 0x10302c2
+ field public static final int Widget_Quantum_Light_TabWidget = 16974531; // 0x10302c3
+ field public static final int Widget_Quantum_Light_TextView = 16974532; // 0x10302c4
+ field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974533; // 0x10302c5
+ field public static final int Widget_Quantum_Light_WebTextView = 16974534; // 0x10302c6
+ field public static final int Widget_Quantum_Light_WebView = 16974535; // 0x10302c7
+ field public static final int Widget_Quantum_ListPopupWindow = 16974448; // 0x1030270
+ field public static final int Widget_Quantum_ListView = 16974449; // 0x1030271
+ field public static final int Widget_Quantum_ListView_DropDown = 16974450; // 0x1030272
+ field public static final int Widget_Quantum_MediaRouteButton = 16974451; // 0x1030273
+ field public static final int Widget_Quantum_PopupMenu = 16974452; // 0x1030274
+ field public static final int Widget_Quantum_PopupMenu_Overflow = 16974453; // 0x1030275
+ field public static final int Widget_Quantum_PopupWindow = 16974454; // 0x1030276
+ field public static final int Widget_Quantum_ProgressBar = 16974455; // 0x1030277
+ field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974456; // 0x1030278
+ field public static final int Widget_Quantum_ProgressBar_Large = 16974457; // 0x1030279
+ field public static final int Widget_Quantum_ProgressBar_Small = 16974458; // 0x103027a
+ field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974459; // 0x103027b
+ field public static final int Widget_Quantum_RatingBar = 16974460; // 0x103027c
+ field public static final int Widget_Quantum_RatingBar_Indicator = 16974461; // 0x103027d
+ field public static final int Widget_Quantum_RatingBar_Small = 16974462; // 0x103027e
+ field public static final int Widget_Quantum_ScrollView = 16974463; // 0x103027f
+ field public static final int Widget_Quantum_SeekBar = 16974464; // 0x1030280
+ field public static final int Widget_Quantum_SegmentedButton = 16974465; // 0x1030281
+ field public static final int Widget_Quantum_Spinner = 16974467; // 0x1030283
+ field public static final int Widget_Quantum_StackView = 16974466; // 0x1030282
+ field public static final int Widget_Quantum_Tab = 16974468; // 0x1030284
+ field public static final int Widget_Quantum_TabWidget = 16974469; // 0x1030285
+ field public static final int Widget_Quantum_TextView = 16974470; // 0x1030286
+ field public static final int Widget_Quantum_TextView_SpinnerItem = 16974471; // 0x1030287
+ field public static final int Widget_Quantum_WebTextView = 16974472; // 0x1030288
+ field public static final int Widget_Quantum_WebView = 16974473; // 0x1030289
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
@@ -3307,7 +3306,6 @@
method public void onUserInteraction();
method protected void onUserLeaveHint();
method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
- method public void onWindowDismissed();
method public void onWindowFocusChanged(boolean);
method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
method public void openContextMenu(android.view.View);
@@ -3320,7 +3318,6 @@
method public final boolean requestWindowFeature(int);
method public final void runOnUiThread(java.lang.Runnable);
method public void setActionBar(android.widget.Toolbar);
- method public void setActivityLabelAndIcon(java.lang.CharSequence, android.graphics.Bitmap);
method public void setActivityTransitionListener(android.app.ActivityOptions.ActivityTransitionListener);
method public void setContentTransitionManager(android.transition.TransitionManager);
method public void setContentView(int);
@@ -3338,6 +3335,7 @@
method public final void setProgressBarIndeterminate(boolean);
method public final void setProgressBarIndeterminateVisibility(boolean);
method public final void setProgressBarVisibility(boolean);
+ method public void setRecentsActivityValues(android.app.ActivityManager.RecentsActivityValues);
method public void setRequestedOrientation(int);
method public final void setResult(int);
method public final void setResult(int, android.content.Intent);
@@ -3458,8 +3456,7 @@
method public void readFromParcel(android.os.Parcel);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
- field public android.graphics.Bitmap activityIcon;
- field public java.lang.CharSequence activityLabel;
+ field public android.app.ActivityManager.RecentsActivityValues activityValues;
field public android.content.Intent baseIntent;
field public java.lang.CharSequence description;
field public int id;
@@ -3467,6 +3464,21 @@
field public int persistentId;
}
+ public static class ActivityManager.RecentsActivityValues implements android.os.Parcelable {
+ ctor public ActivityManager.RecentsActivityValues(android.app.ActivityManager.RecentsActivityValues);
+ ctor public ActivityManager.RecentsActivityValues(java.lang.CharSequence, android.graphics.Bitmap, int);
+ ctor public ActivityManager.RecentsActivityValues(java.lang.CharSequence, android.graphics.Bitmap);
+ ctor public ActivityManager.RecentsActivityValues(java.lang.CharSequence);
+ ctor public ActivityManager.RecentsActivityValues();
+ method public int describeContents();
+ method public void readFromParcel(android.os.Parcel);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ field public int colorPrimary;
+ field public android.graphics.Bitmap icon;
+ field public java.lang.CharSequence label;
+ }
+
public static class ActivityManager.RunningAppProcessInfo implements android.os.Parcelable {
ctor public ActivityManager.RunningAppProcessInfo();
ctor public ActivityManager.RunningAppProcessInfo(java.lang.String, int, java.lang.String[]);
@@ -3849,7 +3861,6 @@
method public boolean onTouchEvent(android.view.MotionEvent);
method public boolean onTrackballEvent(android.view.MotionEvent);
method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
- method public void onWindowDismissed();
method public void onWindowFocusChanged(boolean);
method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
method public void openContextMenu(android.view.View);
@@ -4996,12 +5007,12 @@
}
public class DevicePolicyManager {
+ method public void addForwardingIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName);
method public void addUserRestriction(android.content.ComponentName, java.lang.String);
method public void clearForwardingIntentFilters(android.content.ComponentName);
method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
- method public void forwardMatchingIntents(android.content.ComponentName, android.content.IntentFilter, int);
method public java.util.List<android.content.ComponentName> getActiveAdmins();
method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String);
method public boolean getCameraDisabled(android.content.ComponentName);
@@ -5299,6 +5310,7 @@
field public static final int RESIZE_VERTICAL = 2; // 0x2
field public static final int WIDGET_CATEGORY_HOME_SCREEN = 1; // 0x1
field public static final int WIDGET_CATEGORY_KEYGUARD = 2; // 0x2
+ field public static final int WIDGET_CATEGORY_RECENTS = 4; // 0x4
field public int autoAdvanceViewId;
field public android.content.ComponentName configure;
field public int icon;
@@ -6602,6 +6614,7 @@
field public static final java.lang.String DISPLAY_SERVICE = "display";
field public static final java.lang.String DOWNLOAD_SERVICE = "download";
field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
+ field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint";
field public static final java.lang.String HDMI_CEC_SERVICE = "hdmi_cec";
field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
field public static final java.lang.String INPUT_SERVICE = "input";
@@ -10722,6 +10735,7 @@
method public void releaseTexImage();
method public void setDefaultBufferSize(int, int);
method public void setOnFrameAvailableListener(android.graphics.SurfaceTexture.OnFrameAvailableListener);
+ method public void setOnFrameAvailableListener(android.graphics.SurfaceTexture.OnFrameAvailableListener, android.os.Handler);
method public void updateTexImage();
}
@@ -11217,19 +11231,11 @@
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 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();
}
}
@@ -11992,6 +11998,8 @@
field public static final int CONTROL_SCENE_MODE_STEADYPHOTO = 11; // 0xb
field public static final int CONTROL_SCENE_MODE_SUNSET = 10; // 0xa
field public static final int CONTROL_SCENE_MODE_THEATRE = 7; // 0x7
+ field public static final int CONTROL_VIDEO_STABILIZATION_MODE_OFF = 0; // 0x0
+ field public static final int CONTROL_VIDEO_STABILIZATION_MODE_ON = 1; // 0x1
field public static final int EDGE_MODE_FAST = 1; // 0x1
field public static final int EDGE_MODE_HIGH_QUALITY = 2; // 0x2
field public static final int EDGE_MODE_OFF = 0; // 0x0
@@ -12165,17 +12173,29 @@
method public int getSequenceId();
field public static final android.hardware.camera2.CameraMetadata.Key BLACK_LEVEL_LOCK;
field public static final android.hardware.camera2.CameraMetadata.Key COLOR_CORRECTION_GAINS;
+ field public static final android.hardware.camera2.CameraMetadata.Key COLOR_CORRECTION_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key COLOR_CORRECTION_TRANSFORM;
+ field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_ANTIBANDING_MODE;
+ field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_EXPOSURE_COMPENSATION;
+ field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_LOCK;
field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_MODE;
+ field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_PRECAPTURE_TRIGGER;
field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_REGIONS;
field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_STATE;
+ field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_TARGET_FPS_RANGE;
field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_REGIONS;
field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_STATE;
+ field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_TRIGGER;
+ field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_LOCK;
field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_REGIONS;
field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_STATE;
+ field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_CAPTURE_INTENT;
+ field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_EFFECT_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_MODE;
+ field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_SCENE_MODE;
+ field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_VIDEO_STABILIZATION_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key EDGE_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key FLASH_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key FLASH_STATE;
@@ -12206,6 +12226,7 @@
field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_PROFILE_TONE_CURVE;
field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_SENSITIVITY;
field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEMPERATURE;
+ field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEST_PATTERN_DATA;
field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEST_PATTERN_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TIMESTAMP;
field public static final android.hardware.camera2.CameraMetadata.Key SHADING_MODE;
@@ -12214,6 +12235,7 @@
field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_HOT_PIXEL_MAP;
field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_HOT_PIXEL_MAP_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_LENS_SHADING_MAP;
+ field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_LENS_SHADING_MAP_MODE;
field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_SCENE_FLICKER;
field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_BLUE;
field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_GREEN;
@@ -12221,6 +12243,14 @@
field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_MODE;
}
+ public final class ColorSpaceTransform {
+ ctor public ColorSpaceTransform(android.hardware.camera2.Rational[]);
+ ctor public ColorSpaceTransform(int[]);
+ method public void copyElements(android.hardware.camera2.Rational[], int);
+ method public void copyElements(int[], int);
+ method public android.hardware.camera2.Rational getElement(int, int);
+ }
+
public final class Face {
method public android.graphics.Rect getBounds();
method public int getId();
@@ -12233,18 +12263,83 @@
field public static final int SCORE_MIN = 1; // 0x1
}
+ public final class LensShadingMap {
+ method public void copyGainFactors(float[], int);
+ method public int getColumnCount();
+ method public float getGainFactor(int, int, int);
+ method public int getGainFactorCount();
+ method public android.hardware.camera2.RggbChannelVector getGainFactorVector(int, int);
+ method public int getRowCount();
+ field public static final float MINIMUM_GAIN_FACTOR = 1.0f;
+ }
+
+ public final class MeteringRectangle {
+ ctor public MeteringRectangle(int, int, int, int, int);
+ ctor public MeteringRectangle(android.graphics.Point, android.util.Size, int);
+ ctor public MeteringRectangle(android.graphics.Rect, int);
+ method public boolean equals(android.hardware.camera2.MeteringRectangle);
+ method public int getHeight();
+ method public int getMeteringWeight();
+ method public android.graphics.Rect getRect();
+ method public android.util.Size getSize();
+ method public android.graphics.Point getUpperLeftPoint();
+ method public int getWidth();
+ method public int getX();
+ method public int getY();
+ }
+
public final class Rational {
ctor public Rational(int, int);
method public int getDenominator();
method public int getNumerator();
}
+ public final class RggbChannelVector {
+ ctor public RggbChannelVector(float, float, float, float);
+ method public void copyTo(float[], int);
+ method public float getBlue();
+ method public float getComponent(int);
+ method public float getGreenEven();
+ method public float getGreenOdd();
+ method public final float getRed();
+ field public static final int BLUE = 3; // 0x3
+ field public static final int COUNT = 4; // 0x4
+ field public static final int GREEN_EVEN = 1; // 0x1
+ field public static final int GREEN_ODD = 2; // 0x2
+ field public static final int RED = 0; // 0x0
+ }
+
public final class Size {
ctor public Size(int, int);
method public final int getHeight();
method public final int getWidth();
}
+ public final class StreamConfigurationMap {
+ method public final int[] getOutputFormats();
+ method public long getOutputMinFrameDuration(int, android.util.Size);
+ method public long getOutputMinFrameDuration(java.lang.Class<T>, android.util.Size);
+ method public android.util.Size[] getOutputSizes(java.lang.Class<T>);
+ method public android.util.Size[] getOutputSizes(int);
+ method public long getOutputStallDuration(int, android.util.Size);
+ method public long getOutputStallDuration(java.lang.Class<T>, android.util.Size);
+ method public boolean isOutputSupportedFor(int);
+ method public static boolean isOutputSupportedFor(java.lang.Class<T>);
+ method public boolean isOutputSupportedFor(android.view.Surface);
+ }
+
+ public final class TonemapCurve {
+ method public void copyColorCurve(int, float[], int);
+ method public android.graphics.PointF getPoint(int, int);
+ method public int getPointCount(int);
+ field public static final int CHANNEL_BLUE = 2; // 0x2
+ field public static final int CHANNEL_GREEN = 1; // 0x1
+ field public static final int CHANNEL_RED = 0; // 0x0
+ field public static final float LEVEL_BLACK = 0.0f;
+ field public static final float LEVEL_WHITE = 1.0f;
+ field public static final int POINT_SIZE = 2; // 0x2
+ }
+
}
package android.hardware.display {
@@ -12377,6 +12472,7 @@
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
+ field public static final int UNKNOWN_VENDOR_ID = 16777215; // 0xffffff
}
public final class HdmiCecClient {
@@ -12418,6 +12514,7 @@
method public int getSource();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
+ field public static final byte[] EMPTY_PARAM;
}
}
@@ -15203,6 +15300,7 @@
method public long getLong(java.lang.String);
method public android.media.Rating getRating(java.lang.String);
method public java.lang.String getString(java.lang.String);
+ method public int size();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
field public static final java.lang.String METADATA_KEY_ALBUM = "android.media.metadata.ALBUM";
@@ -24948,7 +25046,6 @@
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
method public boolean onSearchRequested();
method public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
- method public void onWindowDismissed();
method public void onWindowFocusChanged(boolean);
method public android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
method public void setContentView(int);
@@ -24963,6 +25060,36 @@
}
+package android.service.fingerprint {
+
+ public class FingerprintManager {
+ ctor public FingerprintManager(android.content.Context);
+ method public void enroll(long);
+ method public void remove(int);
+ method public void startListening(android.service.fingerprint.FingerprintManagerReceiver);
+ method public void stopListening();
+ field protected static final boolean DEBUG = true;
+ field public static final int FINGERPRINT_ERROR = -1; // 0xffffffff
+ field public static final int FINGERPRINT_ERROR_BAD_CAPTURE = 2; // 0x2
+ field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1
+ field public static final int FINGERPRINT_ERROR_NO_RECEIVER = -10; // 0xfffffff6
+ field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4
+ field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3
+ field public static final int FINGERPRINT_SCANNED = 1; // 0x1
+ field public static final int FINGERPRINT_TEMPLATE_ENROLLING = 2; // 0x2
+ field public static final int FINGERPRINT_TEMPLATE_REMOVED = 4; // 0x4
+ }
+
+ public class FingerprintManagerReceiver {
+ ctor public FingerprintManagerReceiver();
+ method public void onEnrollResult(int, int);
+ method public void onError(int);
+ method public void onRemoved(int);
+ method public void onScanned(int, int);
+ }
+
+}
+
package android.service.notification {
public abstract class NotificationListenerService extends android.app.Service {
@@ -25044,23 +25171,53 @@
public class VoiceInteractionService extends android.app.Service {
ctor public VoiceInteractionService();
method public android.os.IBinder onBind(android.content.Intent);
- method public void startVoiceActivity(android.content.Intent, android.os.Bundle);
+ method public void startSession(android.os.Bundle);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService";
field public static final java.lang.String SERVICE_META_DATA = "android.voice_interaction";
}
- public abstract class VoiceInteractionSession {
+ public abstract class VoiceInteractionSession implements android.view.KeyEvent.Callback {
ctor public VoiceInteractionSession(android.content.Context);
ctor public VoiceInteractionSession(android.content.Context, android.os.Handler);
+ method public void finish();
+ method public android.view.LayoutInflater getLayoutInflater();
+ method public android.app.Dialog getWindow();
+ method public void hideWindow();
+ method public void onBackPressed();
method public abstract void onCancel(android.service.voice.VoiceInteractionSession.Request);
+ method public void onCloseSystemDialogs();
method public abstract void onCommand(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.String, android.os.Bundle);
+ method public void onComputeInsets(android.service.voice.VoiceInteractionSession.Insets);
method public abstract void onConfirm(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.String, android.os.Bundle);
+ method public void onCreate(android.os.Bundle);
+ method public android.view.View onCreateContentView();
+ method public void onDestroy();
method public abstract boolean[] onGetSupportedCommands(android.service.voice.VoiceInteractionSession.Caller, java.lang.String[]);
+ method public boolean onKeyDown(int, android.view.KeyEvent);
+ method public boolean onKeyLongPress(int, android.view.KeyEvent);
+ method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
+ method public boolean onKeyUp(int, android.view.KeyEvent);
+ method public void onTaskFinished(android.content.Intent, int);
+ method public void onTaskStarted(android.content.Intent, int);
+ method public void setContentView(android.view.View);
+ method public void setTheme(int);
+ method public void showWindow();
+ method public void startVoiceActivity(android.content.Intent);
}
public static class VoiceInteractionSession.Caller {
}
+ public static final class VoiceInteractionSession.Insets {
+ ctor public VoiceInteractionSession.Insets();
+ field public static final int TOUCHABLE_INSETS_CONTENT = 1; // 0x1
+ field public static final int TOUCHABLE_INSETS_FRAME = 0; // 0x0
+ field public static final int TOUCHABLE_INSETS_REGION = 3; // 0x3
+ field public int contentTopInsets;
+ field public int touchableInsets;
+ field public final android.graphics.Region touchableRegion;
+ }
+
public static class VoiceInteractionSession.Request {
method public void sendCancelResult();
method public void sendCommandResult(boolean, android.os.Bundle);
@@ -28712,6 +28869,25 @@
method public void set(T, V);
}
+ public final class Range {
+ ctor public Range(T, T);
+ method public static android.util.Range<T> create(T, T);
+ method public T getLower();
+ method public T getUpper();
+ }
+
+ public final class Size {
+ ctor public Size(int, int);
+ method public int getHeight();
+ method public int getWidth();
+ }
+
+ public final class SizeF {
+ ctor public SizeF(float, float);
+ method public float getHeight();
+ method public float getWidth();
+ }
+
public class SparseArray implements java.lang.Cloneable {
ctor public SparseArray();
ctor public SparseArray(int);
@@ -30847,7 +31023,7 @@
method public static int getDoubleTapTimeout();
method public static deprecated int getEdgeSlop();
method public static deprecated int getFadingEdgeLength();
- method public static long getGlobalActionKeyTimeout();
+ method public static deprecated long getGlobalActionKeyTimeout();
method public static int getJumpTapTimeout();
method public static int getKeyRepeatDelay();
method public static int getKeyRepeatTimeout();
@@ -31418,7 +31594,6 @@
method public abstract boolean onPreparePanel(int, android.view.View, android.view.Menu);
method public abstract boolean onSearchRequested();
method public abstract void onWindowAttributesChanged(android.view.WindowManager.LayoutParams);
- method public abstract void onWindowDismissed();
method public abstract void onWindowFocusChanged(boolean);
method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
}
@@ -31452,26 +31627,17 @@
method public abstract void onFocusLost(android.view.WindowId);
}
- public class WindowInsets {
+ public final class WindowInsets {
ctor public WindowInsets(android.view.WindowInsets);
- method public android.view.WindowInsets cloneWithSystemWindowInsets(int, int, int, int);
- method public android.view.WindowInsets cloneWithSystemWindowInsetsConsumed();
- method public android.view.WindowInsets cloneWithSystemWindowInsetsConsumed(boolean, boolean, boolean, boolean);
- method public android.view.WindowInsets cloneWithWindowDecorInsets(int, int, int, int);
- method public android.view.WindowInsets cloneWithWindowDecorInsetsConsumed();
- method public android.view.WindowInsets cloneWithWindowDecorInsetsConsumed(boolean, boolean, boolean, boolean);
+ method public android.view.WindowInsets consumeSystemWindowInsets();
method public int getSystemWindowInsetBottom();
method public int getSystemWindowInsetLeft();
method public int getSystemWindowInsetRight();
method public int getSystemWindowInsetTop();
- method public int getWindowDecorInsetBottom();
- method public int getWindowDecorInsetLeft();
- method public int getWindowDecorInsetRight();
- method public int getWindowDecorInsetTop();
method public boolean hasInsets();
method public boolean hasSystemWindowInsets();
- method public boolean hasWindowDecorInsets();
method public boolean isRound();
+ method public android.view.WindowInsets replaceSystemWindowInsets(int, int, int, int);
}
public abstract interface WindowManager implements android.view.ViewManager {
@@ -32695,6 +32861,16 @@
package android.webkit {
+ public abstract interface ClientCertRequest {
+ method public abstract void cancel();
+ method public abstract java.lang.String getHost();
+ method public abstract java.lang.String[] getKeyTypes();
+ method public abstract int getPort();
+ method public abstract java.security.Principal[] getPrincipals();
+ method public abstract void ignore();
+ method public abstract void proceed(java.security.PrivateKey, java.security.cert.X509Certificate[]);
+ }
+
public class ConsoleMessage {
ctor public ConsoleMessage(java.lang.String, java.lang.String, int, android.webkit.ConsoleMessage.MessageLevel);
method public int lineNumber();
@@ -32788,6 +32964,16 @@
method public boolean hasMimeType(java.lang.String);
}
+ public abstract interface PermissionRequest {
+ method public abstract void deny();
+ method public abstract android.net.Uri getOrigin();
+ method public abstract long getResources();
+ method public abstract void grant(long);
+ field public static final long RESOURCE_AUDIO_CAPTURE = 4L; // 0x4L
+ field public static final long RESOURCE_GEOLOCATION = 1L; // 0x1L
+ field public static final long RESOURCE_VIDEO_CAPTURE = 2L; // 0x2L
+ }
+
public abstract interface PluginStub {
method public abstract android.view.View getEmbeddedView(int, android.content.Context);
method public abstract android.view.View getFullScreenView(int, android.content.Context);
@@ -32847,6 +33033,8 @@
method public boolean onJsConfirm(android.webkit.WebView, java.lang.String, java.lang.String, android.webkit.JsResult);
method public boolean onJsPrompt(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String, android.webkit.JsPromptResult);
method public deprecated boolean onJsTimeout();
+ method public void onPermissionRequest(android.webkit.PermissionRequest);
+ method public void onPermissionRequestCanceled(android.webkit.PermissionRequest);
method public void onProgressChanged(android.webkit.WebView, int);
method public deprecated void onReachedMaxAppCacheSize(long, long, android.webkit.WebStorage.QuotaUpdater);
method public void onReceivedIcon(android.webkit.WebView, android.graphics.Bitmap);
@@ -32923,6 +33111,7 @@
method public boolean getMediaPlaybackRequiresUserGesture();
method public synchronized int getMinimumFontSize();
method public synchronized int getMinimumLogicalFontSize();
+ method public abstract int getMixedContentMode();
method public deprecated synchronized android.webkit.WebSettings.PluginState getPluginState();
method public synchronized java.lang.String getSansSerifFontFamily();
method public boolean getSaveFormData();
@@ -32967,6 +33156,7 @@
method public void setMediaPlaybackRequiresUserGesture(boolean);
method public synchronized void setMinimumFontSize(int);
method public synchronized void setMinimumLogicalFontSize(int);
+ method public abstract void setMixedContentMode(int);
method public void setNeedInitialFocus(boolean);
method public deprecated synchronized void setPluginState(android.webkit.WebSettings.PluginState);
method public deprecated synchronized void setRenderPriority(android.webkit.WebSettings.RenderPriority);
@@ -32988,6 +33178,9 @@
field public static final int LOAD_DEFAULT = -1; // 0xffffffff
field public static final deprecated int LOAD_NORMAL = 0; // 0x0
field public static final int LOAD_NO_CACHE = 2; // 0x2
+ field public static final int MIXED_CONTENT_ALWAYS_ALLOW = 0; // 0x0
+ field public static final int MIXED_CONTENT_COMPATIBILITY_MODE = 2; // 0x2
+ field public static final int MIXED_CONTENT_NEVER_ALLOW = 1; // 0x1
}
public static final class WebSettings.LayoutAlgorithm extends java.lang.Enum {
@@ -33080,6 +33273,7 @@
method public deprecated boolean canZoomOut();
method public deprecated android.graphics.Picture capturePicture();
method public void clearCache(boolean);
+ method public static void clearClientCertPreferences(java.lang.Runnable);
method public void clearFormData();
method public void clearHistory();
method public void clearMatches();
@@ -33128,6 +33322,7 @@
method public boolean pageUp(boolean);
method public void pauseTimers();
method public void postUrl(java.lang.String, byte[]);
+ method public void preauthorizePermission(android.net.Uri, long);
method public void reload();
method public void removeJavascriptInterface(java.lang.String);
method public void requestFocusNodeHref(android.os.Message);
@@ -33196,6 +33391,7 @@
method public void onLoadResource(android.webkit.WebView, java.lang.String);
method public void onPageFinished(android.webkit.WebView, java.lang.String);
method public void onPageStarted(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
+ method public void onReceivedClientCertRequest(android.webkit.WebView, android.webkit.ClientCertRequest);
method public void onReceivedError(android.webkit.WebView, int, java.lang.String, java.lang.String);
method public void onReceivedHttpAuthRequest(android.webkit.WebView, android.webkit.HttpAuthHandler, java.lang.String, java.lang.String);
method public void onReceivedLoginRequest(android.webkit.WebView, java.lang.String, java.lang.String, java.lang.String);
@@ -49410,6 +49606,7 @@
method public abstract boolean getEnableSessionCreation();
method public abstract java.lang.String[] getEnabledCipherSuites();
method public abstract java.lang.String[] getEnabledProtocols();
+ method public javax.net.ssl.SSLSession getHandshakeSession();
method public abstract javax.net.ssl.SSLEngineResult.HandshakeStatus getHandshakeStatus();
method public abstract boolean getNeedClientAuth();
method public java.lang.String getPeerHost();
@@ -49483,10 +49680,12 @@
ctor public SSLParameters(java.lang.String[]);
ctor public SSLParameters(java.lang.String[], java.lang.String[]);
method public java.lang.String[] getCipherSuites();
+ method public java.lang.String getEndpointIdentificationAlgorithm();
method public boolean getNeedClientAuth();
method public java.lang.String[] getProtocols();
method public boolean getWantClientAuth();
method public void setCipherSuites(java.lang.String[]);
+ method public void setEndpointIdentificationAlgorithm(java.lang.String);
method public void setNeedClientAuth(boolean);
method public void setProtocols(java.lang.String[]);
method public void setWantClientAuth(boolean);
@@ -49587,6 +49786,7 @@
method public abstract boolean getEnableSessionCreation();
method public abstract java.lang.String[] getEnabledCipherSuites();
method public abstract java.lang.String[] getEnabledProtocols();
+ method public javax.net.ssl.SSLSession getHandshakeSession();
method public abstract boolean getNeedClientAuth();
method public javax.net.ssl.SSLParameters getSSLParameters();
method public abstract javax.net.ssl.SSLSession getSession();
@@ -49642,6 +49842,14 @@
method public java.lang.String chooseEngineServerAlias(java.lang.String, java.security.Principal[], javax.net.ssl.SSLEngine);
}
+ public abstract class X509ExtendedTrustManager implements javax.net.ssl.X509TrustManager {
+ ctor public X509ExtendedTrustManager();
+ method public abstract void checkClientTrusted(java.security.cert.X509Certificate[], java.lang.String, java.net.Socket) throws java.security.cert.CertificateException;
+ method public abstract void checkClientTrusted(java.security.cert.X509Certificate[], java.lang.String, javax.net.ssl.SSLEngine) throws java.security.cert.CertificateException;
+ method public abstract void checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String, java.net.Socket) throws java.security.cert.CertificateException;
+ method public abstract void checkServerTrusted(java.security.cert.X509Certificate[], java.lang.String, javax.net.ssl.SSLEngine) throws java.security.cert.CertificateException;
+ }
+
public abstract interface X509KeyManager implements javax.net.ssl.KeyManager {
method public abstract java.lang.String chooseClientAlias(java.lang.String[], java.security.Principal[], java.net.Socket);
method public abstract java.lang.String chooseServerAlias(java.lang.String, java.security.Principal[], java.net.Socket);
diff --git a/core/java/android/animation/TypeEvaluator.java b/core/java/android/animation/TypeEvaluator.java
index 2640457..429c435 100644
--- a/core/java/android/animation/TypeEvaluator.java
+++ b/core/java/android/animation/TypeEvaluator.java
@@ -29,7 +29,7 @@
/**
* This function returns the result of linearly interpolating the start and end values, with
* <code>fraction</code> representing the proportion between the start and end values. The
- * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
+ * calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
* where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
* and <code>t</code> is <code>fraction</code>.
*
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8981c88..af3a92c 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -655,7 +655,8 @@
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
- OnCreateContextMenuListener, ComponentCallbacks2 {
+ OnCreateContextMenuListener, ComponentCallbacks2,
+ Window.OnWindowDismissedCallback {
private static final String TAG = "Activity";
private static final boolean DEBUG_LIFECYCLE = false;
@@ -2519,7 +2520,9 @@
/**
* Called when the main window associated with the activity has been dismissed.
+ * @hide
*/
+ @Override
public void onWindowDismissed() {
finish();
}
@@ -3493,6 +3496,16 @@
}
theme.applyStyle(resid, false);
}
+
+ // Get the primary color and update the RecentsActivityValues for this activity
+ TypedArray a = getTheme().obtainStyledAttributes(com.android.internal.R.styleable.Theme);
+ int colorPrimary = a.getColor(com.android.internal.R.styleable.Theme_colorPrimary, 0);
+ a.recycle();
+ if (colorPrimary != 0) {
+ ActivityManager.RecentsActivityValues v = new ActivityManager.RecentsActivityValues();
+ v.colorPrimary = colorPrimary;
+ setRecentsActivityValues(v);
+ }
}
/**
@@ -4779,31 +4792,26 @@
}
/**
- * Set a label and icon to be used in the Recents task display. When {@link
- * ActivityManager#getRecentTasks} is called, the activities of each task are
- * traversed in order from the topmost activity to the bottommost. As soon as one activity is
- * found with either a non-null label or a non-null icon set by this call the traversal is
- * ended. For each task those values will be returned in {@link
- * ActivityManager.RecentTaskInfo#activityLabel} and {@link
- * ActivityManager.RecentTaskInfo#activityIcon}.
+ * Sets information describing this Activity for presentation inside the Recents System UI. When
+ * {@link ActivityManager#getRecentTasks} is called, the activities of each task are
+ * traversed in order from the topmost activity to the bottommost. The traversal continues for
+ * each property until a suitable value is found. For each task those values will be returned in
+ * {@link android.app.ActivityManager.RecentsActivityValues}.
*
* @see ActivityManager#getRecentTasks
- * @see ActivityManager.RecentTaskInfo
+ * @see android.app.ActivityManager.RecentsActivityValues
*
- * @param activityLabel The label to use in the RecentTaskInfo.
- * @param activityIcon The Bitmap to use in the RecentTaskInfo.
+ * @param values The Recents values that describe this activity.
*/
- public void setActivityLabelAndIcon(CharSequence activityLabel, Bitmap activityIcon) {
- final Bitmap scaledIcon;
- if (activityIcon != null) {
+ public void setRecentsActivityValues(ActivityManager.RecentsActivityValues values) {
+ ActivityManager.RecentsActivityValues activityValues =
+ new ActivityManager.RecentsActivityValues(values);
+ if (values.icon != null) {
final int size = ActivityManager.getLauncherLargeIconSizeInner(this);
- scaledIcon = Bitmap.createScaledBitmap(activityIcon, size, size, true);
- } else {
- scaledIcon = null;
+ activityValues.icon = Bitmap.createScaledBitmap(values.icon, size, size, true);
}
try {
- ActivityManagerNative.getDefault().setActivityLabelAndIcon(mToken, activityLabel,
- scaledIcon);
+ ActivityManagerNative.getDefault().setRecentsActivityValues(mToken, activityValues);
} catch (RemoteException e) {
}
}
@@ -5432,6 +5440,7 @@
mWindow = PolicyManager.makeNewWindow(this);
mWindow.setCallback(this);
+ mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 9239faf..5d809d8 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -475,6 +475,111 @@
}
/**
+ * Information you can set and retrieve about the current activity within Recents.
+ */
+ public static class RecentsActivityValues implements Parcelable {
+ public CharSequence label;
+ public Bitmap icon;
+ public int colorPrimary;
+
+ public RecentsActivityValues(RecentsActivityValues values) {
+ copyFrom(values);
+ }
+
+ /**
+ * Creates the RecentsActivityValues to the specified values.
+ *
+ * @param label A label and description of the current state of this activity.
+ * @param icon An icon that represents the current state of this activity.
+ * @param color A color to override the theme's primary color.
+ */
+ public RecentsActivityValues(CharSequence label, Bitmap icon, int color) {
+ this.label = label;
+ this.icon = icon;
+ this.colorPrimary = color;
+ }
+
+ /**
+ * Creates the RecentsActivityValues to the specified values.
+ *
+ * @param label A label and description of the current state of this activity.
+ * @param icon An icon that represents the current state of this activity.
+ */
+ public RecentsActivityValues(CharSequence label, Bitmap icon) {
+ this(label, icon, 0);
+ }
+
+ /**
+ * Creates the RecentsActivityValues to the specified values.
+ *
+ * @param label A label and description of the current state of this activity.
+ */
+ public RecentsActivityValues(CharSequence label) {
+ this(label, null, 0);
+ }
+
+ public RecentsActivityValues() {
+ this(null, null, 0);
+ }
+
+ private RecentsActivityValues(Parcel source) {
+ readFromParcel(source);
+ }
+
+ /**
+ * Do a shallow copy of another set of activity values.
+ * @hide
+ */
+ public void copyFrom(RecentsActivityValues v) {
+ if (v != null) {
+ label = v.label;
+ icon = v.icon;
+ colorPrimary = v.colorPrimary;
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ TextUtils.writeToParcel(label, dest,
+ Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+ if (icon == null) {
+ dest.writeInt(0);
+ } else {
+ dest.writeInt(1);
+ icon.writeToParcel(dest, 0);
+ }
+ dest.writeInt(colorPrimary);
+ }
+
+ public void readFromParcel(Parcel source) {
+ label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+ icon = source.readInt() > 0 ? Bitmap.CREATOR.createFromParcel(source) : null;
+ colorPrimary = source.readInt();
+ }
+
+ public static final Creator<RecentsActivityValues> CREATOR
+ = new Creator<RecentsActivityValues>() {
+ public RecentsActivityValues createFromParcel(Parcel source) {
+ return new RecentsActivityValues(source);
+ }
+ public RecentsActivityValues[] newArray(int size) {
+ return new RecentsActivityValues[size];
+ }
+ };
+
+ @Override
+ public String toString() {
+ return "RecentsActivityValues Label: " + label + " Icon: " + icon +
+ " colorPrimary: " + colorPrimary;
+ }
+ }
+
+ /**
* Information you can retrieve about tasks that the user has most recently
* started or visited.
*/
@@ -523,16 +628,10 @@
public int userId;
/**
- * The label of the highest activity in the task stack to have set a label using
- * {@link Activity#setActivityLabelAndIcon(CharSequence, android.graphics.Bitmap)}.
+ * The recent activity values for the highest activity in the stack to have set the values.
+ * {@link Activity#setRecentsActivityValues(android.app.ActivityManager.RecentsActivityValues)}.
*/
- public CharSequence activityLabel;
-
- /**
- * The Bitmap icon of the highest activity in the task stack to set a Bitmap using
- * {@link Activity#setActivityLabelAndIcon(CharSequence, android.graphics.Bitmap)}.
- */
- public Bitmap activityIcon;
+ public RecentsActivityValues activityValues;
public RecentTaskInfo() {
}
@@ -555,13 +654,11 @@
ComponentName.writeToParcel(origActivity, dest);
TextUtils.writeToParcel(description, dest,
Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- TextUtils.writeToParcel(activityLabel, dest,
- Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- if (activityIcon == null) {
- dest.writeInt(0);
- } else {
+ if (activityValues != null) {
dest.writeInt(1);
- activityIcon.writeToParcel(dest, 0);
+ activityValues.writeToParcel(dest, 0);
+ } else {
+ dest.writeInt(0);
}
dest.writeInt(stackId);
dest.writeInt(userId);
@@ -573,8 +670,8 @@
baseIntent = source.readInt() > 0 ? Intent.CREATOR.createFromParcel(source) : null;
origActivity = ComponentName.readFromParcel(source);
description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- activityLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
- activityIcon = source.readInt() > 0 ? Bitmap.CREATOR.createFromParcel(source) : null;
+ activityValues = source.readInt() > 0 ?
+ RecentsActivityValues.CREATOR.createFromParcel(source) : null;
stackId = source.readInt();
userId = source.readInt();
}
@@ -791,42 +888,6 @@
* activity -- the task may have been frozen by the system, so that it
* can be restarted in its previous state when next brought to the
* foreground.
- *
- * @param maxNum The maximum number of entries to return in the list. The
- * actual number returned may be smaller, depending on how many tasks the
- * user has started.
- *
- * @param flags Optional flags
- * @param receiver Optional receiver for delayed thumbnails
- *
- * @return Returns a list of RunningTaskInfo records describing each of
- * the running tasks.
- *
- * Some thumbnails may not be available at the time of this call. The optional
- * receiver may be used to receive those thumbnails.
- *
- * @throws SecurityException Throws SecurityException if the caller does
- * not hold the {@link android.Manifest.permission#GET_TASKS} permission.
- *
- * @hide
- */
- public List<RunningTaskInfo> getRunningTasks(int maxNum, int flags, IThumbnailReceiver receiver)
- throws SecurityException {
- try {
- return ActivityManagerNative.getDefault().getTasks(maxNum, flags, receiver);
- } catch (RemoteException e) {
- // System dead, we will be dead too soon!
- return null;
- }
- }
-
- /**
- * Return a list of the tasks that are currently running, with
- * the most recent being first and older ones after in order. Note that
- * "running" does not mean any of the task's code is currently loaded or
- * activity -- the task may have been frozen by the system, so that it
- * can be restarted in its previous state when next brought to the
- * foreground.
*
* <p><b>Note: this method is only intended for debugging and presenting
* task management user interfaces</b>. This should never be used for
@@ -849,7 +910,12 @@
*/
public List<RunningTaskInfo> getRunningTasks(int maxNum)
throws SecurityException {
- return getRunningTasks(maxNum, 0, null);
+ try {
+ return ActivityManagerNative.getDefault().getTasks(maxNum, 0);
+ } catch (RemoteException e) {
+ // System dead, we will be dead too soon!
+ return null;
+ }
}
/**
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index b1c37de..57da21e 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -509,11 +509,7 @@
data.enforceInterface(IActivityManager.descriptor);
int maxNum = data.readInt();
int fl = data.readInt();
- IBinder receiverBinder = data.readStrongBinder();
- IThumbnailReceiver receiver = receiverBinder != null
- ? IThumbnailReceiver.Stub.asInterface(receiverBinder)
- : null;
- List<ActivityManager.RunningTaskInfo> list = getTasks(maxNum, fl, receiver);
+ List<ActivityManager.RunningTaskInfo> list = getTasks(maxNum, fl);
reply.writeNoException();
int N = list != null ? list.size() : -1;
reply.writeInt(N);
@@ -712,17 +708,6 @@
return true;
}
- case REPORT_THUMBNAIL_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- IBinder token = data.readStrongBinder();
- Bitmap thumbnail = data.readInt() != 0
- ? Bitmap.CREATOR.createFromParcel(data) : null;
- CharSequence description = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data);
- reportThumbnail(token, thumbnail, description);
- reply.writeNoException();
- return true;
- }
-
case GET_CONTENT_PROVIDER_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
@@ -2134,13 +2119,12 @@
return true;
}
- case SET_ACTIVITY_LABEL_ICON_TRANSACTION: {
+ case SET_RECENTS_ACTIVITY_VALUES_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
- CharSequence activityLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(data);
- Bitmap activityIcon = data.readInt() > 0
- ? Bitmap.CREATOR.createFromParcel(data) : null;
- setActivityLabelAndIcon(token, activityLabel, activityIcon);
+ ActivityManager.RecentsActivityValues values =
+ ActivityManager.RecentsActivityValues.CREATOR.createFromParcel(data);
+ setRecentsActivityValues(token, values);
reply.writeNoException();
return true;
}
@@ -2678,14 +2662,12 @@
reply.recycle();
return res;
}
- public List getTasks(int maxNum, int flags,
- IThumbnailReceiver receiver) throws RemoteException {
+ public List getTasks(int maxNum, int flags) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(maxNum);
data.writeInt(flags);
- data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
mRemote.transact(GET_TASKS_TRANSACTION, data, reply, 0);
reply.readException();
ArrayList list = null;
@@ -2964,25 +2946,6 @@
reply.recycle();
return res;
}
- public void reportThumbnail(IBinder token,
- Bitmap thumbnail, CharSequence description) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeStrongBinder(token);
- if (thumbnail != null) {
- data.writeInt(1);
- thumbnail.writeToParcel(data, 0);
- } else {
- data.writeInt(0);
- }
- TextUtils.writeToParcel(description, data, 0);
- mRemote.transact(REPORT_THUMBNAIL_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
public ContentProviderHolder getContentProvider(IApplicationThread caller,
String name, int userId, boolean stable) throws RemoteException {
Parcel data = Parcel.obtain();
@@ -4919,21 +4882,14 @@
}
@Override
- public void setActivityLabelAndIcon(IBinder token, CharSequence activityLabel,
- Bitmap activityIcon) throws RemoteException
- {
+ public void setRecentsActivityValues(IBinder token, ActivityManager.RecentsActivityValues values)
+ throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
- TextUtils.writeToParcel(activityLabel, data, 0);
- if (activityIcon != null) {
- data.writeInt(1);
- activityIcon.writeToParcel(data, 0);
- } else {
- data.writeInt(0);
- }
- mRemote.transact(SET_ACTIVITY_LABEL_ICON_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+ values.writeToParcel(data, 0);
+ mRemote.transact(SET_RECENTS_ACTIVITY_VALUES_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
reply.readException();
data.recycle();
reply.recycle();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7dc21b4..3b2ff7f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -821,10 +821,6 @@
sendMessage(H.SUICIDE, null);
}
- public void requestThumbnail(IBinder token) {
- sendMessage(H.REQUEST_THUMBNAIL, token);
- }
-
public void scheduleConfigurationChanged(Configuration config) {
updatePendingConfiguration(config);
sendMessage(H.CONFIGURATION_CHANGED, config);
@@ -1168,7 +1164,7 @@
public static final int CREATE_SERVICE = 114;
public static final int SERVICE_ARGS = 115;
public static final int STOP_SERVICE = 116;
- public static final int REQUEST_THUMBNAIL = 117;
+
public static final int CONFIGURATION_CHANGED = 118;
public static final int CLEAN_UP_CONTEXT = 119;
public static final int GC_WHEN_IDLE = 120;
@@ -1218,7 +1214,6 @@
case CREATE_SERVICE: return "CREATE_SERVICE";
case SERVICE_ARGS: return "SERVICE_ARGS";
case STOP_SERVICE: return "STOP_SERVICE";
- case REQUEST_THUMBNAIL: return "REQUEST_THUMBNAIL";
case CONFIGURATION_CHANGED: return "CONFIGURATION_CHANGED";
case CLEAN_UP_CONTEXT: return "CLEAN_UP_CONTEXT";
case GC_WHEN_IDLE: return "GC_WHEN_IDLE";
@@ -1367,11 +1362,6 @@
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
- case REQUEST_THUMBNAIL:
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "requestThumbnail");
- handleRequestThumbnail((IBinder)msg.obj);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- break;
case CONFIGURATION_CHANGED:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
@@ -3817,28 +3807,6 @@
handleLaunchActivity(r, currentIntent);
}
- private void handleRequestThumbnail(IBinder token) {
- ActivityClientRecord r = mActivities.get(token);
- Bitmap thumbnail = createThumbnailBitmap(r);
- CharSequence description = null;
- try {
- description = r.activity.onCreateDescription();
- } catch (Exception e) {
- if (!mInstrumentation.onException(r.activity, e)) {
- throw new RuntimeException(
- "Unable to create description of activity "
- + r.intent.getComponent().toShortString()
- + ": " + e.toString(), e);
- }
- }
- //System.out.println("Reporting top thumbnail " + thumbnail);
- try {
- ActivityManagerNative.getDefault().reportThumbnail(
- token, thumbnail, description);
- } catch (RemoteException ex) {
- }
- }
-
ArrayList<ComponentCallbacks2> collectComponentCallbacks(
boolean allActivities, Configuration newConfig) {
ArrayList<ComponentCallbacks2> callbacks
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 3c1455b..3eb2fea 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
@@ -30,6 +31,7 @@
import android.transition.TransitionSet;
import android.util.ArrayMap;
import android.util.Pair;
+import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroupOverlay;
@@ -138,6 +140,10 @@
private static final String KEY_HEIGHT = "shared_element:height";
private static final String KEY_NAME = "shared_element:name";
private static final String KEY_BITMAP = "shared_element:bitmap";
+ private static final String KEY_SCALE_TYPE = "shared_element:scaleType";
+ private static final String KEY_IMAGE_MATRIX = "shared_element:imageMatrix";
+
+ private static final ImageView.ScaleType[] SCALE_TYPE_VALUES = ImageView.ScaleType.values();
/**
* Sent by the exiting coordinator (either EnterTransitionCoordinator
@@ -322,7 +328,8 @@
final ArrayList<View> accepted = new ArrayList<View>();
final ArrayList<View> rejected = new ArrayList<View>();
createSharedElementImages(accepted, rejected, sharedElementNames, state);
- setSharedElementState(state, accepted);
+ ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>> originalImageViewState =
+ setSharedElementState(state, accepted);
handleRejected(rejected);
if (getViewsTransition() != null) {
@@ -331,6 +338,7 @@
setViewVisibility(mSharedElements, View.VISIBLE);
Transition transition = beginTransition(mEnteringViews, true, allowOverlappingTransitions(),
true);
+ setOriginalImageViewState(originalImageViewState);
if (allowOverlappingTransitions()) {
onStartEnterTransition(transition, mEnteringViews);
@@ -568,15 +576,22 @@
mEpicenterCallback.setEpicenter(epicenter);
}
- private void setSharedElementState(Bundle sharedElementState,
- final ArrayList<View> acceptedOverlayViews) {
+ private ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>> setSharedElementState(
+ Bundle sharedElementState, final ArrayList<View> acceptedOverlayViews) {
+ ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>> originalImageState =
+ new ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>>();
final int[] tempLoc = new int[2];
if (sharedElementState != null) {
for (int i = 0; i < mSharedElements.size(); i++) {
View sharedElement = mSharedElements.get(i);
+ String name = mTargetSharedNames.get(i);
+ Pair<ImageView.ScaleType, Matrix> originalState = getOldImageState(sharedElement,
+ name, sharedElementState);
+ if (originalState != null) {
+ originalImageState.put((ImageView) sharedElement, originalState);
+ }
View parent = (View) sharedElement.getParent();
parent.getLocationOnScreen(tempLoc);
- String name = mTargetSharedNames.get(i);
setSharedElementState(sharedElement, name, sharedElementState, tempLoc);
sharedElement.requestLayout();
}
@@ -596,6 +611,29 @@
}
}
);
+ return originalImageState;
+ }
+
+ private static Pair<ImageView.ScaleType, Matrix> getOldImageState(View view, String name,
+ Bundle transitionArgs) {
+ if (!(view instanceof ImageView)) {
+ return null;
+ }
+ Bundle bundle = transitionArgs.getBundle(name);
+ int scaleTypeInt = bundle.getInt(KEY_SCALE_TYPE, -1);
+ if (scaleTypeInt < 0) {
+ return null;
+ }
+
+ ImageView imageView = (ImageView) view;
+ ImageView.ScaleType originalScaleType = imageView.getScaleType();
+
+ Matrix originalMatrix = null;
+ if (originalScaleType == ImageView.ScaleType.MATRIX) {
+ originalMatrix = new Matrix(imageView.getImageMatrix());
+ }
+
+ return Pair.create(originalScaleType, originalMatrix);
}
/**
@@ -614,6 +652,21 @@
return;
}
+ if (view instanceof ImageView) {
+ int scaleTypeInt = sharedElementBundle.getInt(KEY_SCALE_TYPE, -1);
+ if (scaleTypeInt >= 0) {
+ ImageView imageView = (ImageView) view;
+ ImageView.ScaleType scaleType = SCALE_TYPE_VALUES[scaleTypeInt];
+ imageView.setScaleType(scaleType);
+ if (scaleType == ImageView.ScaleType.MATRIX) {
+ float[] matrixValues = sharedElementBundle.getFloatArray(KEY_IMAGE_MATRIX);
+ Matrix matrix = new Matrix();
+ matrix.setValues(matrixValues);
+ imageView.setImageMatrix(matrix);
+ }
+ }
+ }
+
float z = sharedElementBundle.getFloat(KEY_TRANSLATION_Z);
view.setTranslationZ(z);
@@ -666,6 +719,17 @@
view.draw(canvas);
sharedElementBundle.putParcelable(KEY_BITMAP, bitmap);
+ if (view instanceof ImageView) {
+ ImageView imageView = (ImageView) view;
+ int scaleTypeInt = scaleTypeToInt(imageView.getScaleType());
+ sharedElementBundle.putInt(KEY_SCALE_TYPE, scaleTypeInt);
+ if (imageView.getScaleType() == ImageView.ScaleType.MATRIX) {
+ float[] matrix = new float[9];
+ imageView.getImageMatrix().getValues(matrix);
+ sharedElementBundle.putFloatArray(KEY_IMAGE_MATRIX, matrix);
+ }
+ }
+
transitionArgs.putBundle(name, sharedElementBundle);
}
@@ -829,6 +893,25 @@
}
}
+ private static void setOriginalImageViewState(
+ ArrayMap<ImageView, Pair<ImageView.ScaleType, Matrix>> originalState) {
+ for (int i = 0; i < originalState.size(); i++) {
+ ImageView imageView = originalState.keyAt(i);
+ Pair<ImageView.ScaleType, Matrix> state = originalState.valueAt(i);
+ imageView.setScaleType(state.first);
+ imageView.setImageMatrix(state.second);
+ }
+ }
+
+ private static int scaleTypeToInt(ImageView.ScaleType scaleType) {
+ for (int i = 0; i < SCALE_TYPE_VALUES.length; i++) {
+ if (scaleType == SCALE_TYPE_VALUES[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
private static class FixedEpicenterCallback extends Transition.EpicenterCallback {
private Rect mEpicenter;
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index a810134..097c64e 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -33,6 +33,7 @@
import android.view.Surface;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
+import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import dalvik.system.CloseGuard;
@@ -51,6 +52,7 @@
private int mWidth;
private int mHeight;
private Surface mSurface;
+ private int mLastVisibility;
// Only one IIntentSender or Intent may be queued at a time. Most recent one wins.
IIntentSender mQueuedPendingIntent;
@@ -95,6 +97,8 @@
mMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(mMetrics);
+ mLastVisibility = getVisibility();
+
if (DEBUG) Log.v(TAG, "ctor()");
}
@@ -103,6 +107,26 @@
mTextureView.layout(0, 0, r - l, b - t);
}
+ @Override
+ protected void onVisibilityChanged(View changedView, int visibility) {
+ super.onVisibilityChanged(changedView, visibility);
+
+ if (mSurface != null) {
+ try {
+ if (visibility == View.GONE) {
+ mActivityContainer.setSurface(null, mWidth, mHeight, mMetrics.densityDpi);
+ } else if (mLastVisibility == View.GONE) {
+ // Don't change surface when going between View.VISIBLE and View.INVISIBLE.
+ mActivityContainer.setSurface(mSurface, mWidth, mHeight, mMetrics.densityDpi);
+ }
+ } catch (RemoteException e) {
+ throw new RuntimeException(
+ "ActivityView: Unable to set surface of ActivityContainer. " + e);
+ }
+ }
+ mLastVisibility = visibility;
+ }
+
private boolean injectInputEvent(InputEvent event) {
return mActivityContainer != null && mActivityContainer.injectEvent(event);
}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index ab62427..efd3d86 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1440,6 +1440,31 @@
return null;
}
+ /**
+ * @hide
+ */
+ @Override
+ public void addForwardingIntentFilter(IntentFilter filter, boolean removable, int userIdOrig,
+ int userIdDest) {
+ try {
+ mPM.addForwardingIntentFilter(filter, removable, userIdOrig, userIdDest);
+ } catch (RemoteException e) {
+ // Should never happen!
+ }
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void clearForwardingIntentFilters(int userIdOrig) {
+ try {
+ mPM.clearForwardingIntentFilters(userIdOrig);
+ } catch (RemoteException e) {
+ // Should never happen!
+ }
+ }
+
private final ContextImpl mContext;
private final IPackageManager mPM;
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index fcc7f8e..7f2fb59 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -312,14 +312,6 @@
return true;
}
- case REQUEST_THUMBNAIL_TRANSACTION:
- {
- data.enforceInterface(IApplicationThread.descriptor);
- IBinder b = data.readStrongBinder();
- requestThumbnail(b);
- return true;
- }
-
case SCHEDULE_CONFIGURATION_CHANGED_TRANSACTION:
{
data.enforceInterface(IApplicationThread.descriptor);
@@ -986,16 +978,6 @@
data.recycle();
}
- public final void requestThumbnail(IBinder token)
- throws RemoteException {
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken(IApplicationThread.descriptor);
- data.writeStrongBinder(token);
- mRemote.transact(REQUEST_THUMBNAIL_TRANSACTION, data, null,
- IBinder.FLAG_ONEWAY);
- data.recycle();
- }
-
public final void scheduleConfigurationChanged(Configuration config)
throws RemoteException {
Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index a4b2651..c621696 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -106,6 +106,9 @@
import android.os.storage.StorageManager;
import android.print.IPrintManager;
import android.print.PrintManager;
+import android.service.fingerprint.FingerprintManager;
+import android.service.fingerprint.FingerprintManagerReceiver;
+import android.service.fingerprint.FingerprintService;
import android.telephony.TelephonyManager;
import android.tv.ITvInputManager;
import android.tv.TvInputManager;
@@ -451,6 +454,11 @@
return new KeyguardManager();
}});
+ registerService(FINGERPRINT_SERVICE, new ServiceFetcher() {
+ public Object createService(ContextImpl ctx) {
+ return new FingerprintManager(ctx);
+ }});
+
registerService(LAYOUT_INFLATER_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return PolicyManager.makeNewLayoutInflater(ctx.getOuterContext());
@@ -473,14 +481,14 @@
registerService(NOTIFICATION_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
final Context outerContext = ctx.getOuterContext();
- // TODO: Why are we not just using the theme attribute
- // that defines the dialog theme?
return new NotificationManager(
new ContextThemeWrapper(outerContext,
- outerContext.getResources().selectSystemTheme(0,
+ Resources.selectSystemTheme(0,
outerContext.getApplicationInfo().targetSdkVersion,
- com.android.internal.R.array.system_theme_sdks,
- com.android.internal.R.array.system_theme_dialog_styles)),
+ 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_Light_Dialog)),
ctx.mMainThread.getHandler());
}});
@@ -731,7 +739,7 @@
@Override
public Resources.Theme getTheme() {
if (mTheme == null) {
- mThemeResource = mResources.selectDefaultTheme(mThemeResource,
+ mThemeResource = Resources.selectDefaultTheme(mThemeResource,
getOuterContext().getApplicationInfo().targetSdkVersion);
mTheme = mResources.newTheme();
mTheme.applyStyle(mThemeResource, true);
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 07583fd..12d4513 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -79,7 +79,7 @@
* </div>
*/
public class Dialog implements DialogInterface, Window.Callback,
- KeyEvent.Callback, OnCreateContextMenuListener {
+ KeyEvent.Callback, OnCreateContextMenuListener, Window.OnWindowDismissedCallback {
private static final String TAG = "Dialog";
private Activity mOwnerActivity;
@@ -165,6 +165,7 @@
Window w = PolicyManager.makeNewWindow(mContext);
mWindow = w;
w.setCallback(this);
+ w.setOnWindowDismissedCallback(this);
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);
mListenersHandler = new ListenersHandler(this);
@@ -708,6 +709,8 @@
public void onDetachedFromWindow() {
}
+ /** @hide */
+ @Override
public void onWindowDismissed() {
dismiss();
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 6b94c4e..2e9cdf3b7 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -111,8 +111,7 @@
public void activityDestroyed(IBinder token) throws RemoteException;
public String getCallingPackage(IBinder token) throws RemoteException;
public ComponentName getCallingActivity(IBinder token) throws RemoteException;
- public List<RunningTaskInfo> getTasks(int maxNum, int flags,
- IThumbnailReceiver receiver) throws RemoteException;
+ public List<RunningTaskInfo> getTasks(int maxNum, int flags) throws RemoteException;
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
int flags, int userId) throws RemoteException;
public ActivityManager.TaskThumbnails getTaskThumbnails(int taskId) throws RemoteException;
@@ -131,9 +130,6 @@
public boolean isInHomeStack(int taskId) throws RemoteException;
public void setFocusedStack(int stackId) throws RemoteException;
public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException;
- /* oneway */
- public void reportThumbnail(IBinder token,
- Bitmap thumbnail, CharSequence description) throws RemoteException;
public ContentProviderHolder getContentProvider(IApplicationThread caller,
String name, int userId, boolean stable) throws RemoteException;
public ContentProviderHolder getContentProviderExternal(String name, int userId, IBinder token)
@@ -439,8 +435,8 @@
public boolean isInLockTaskMode() throws RemoteException;
/** @hide */
- public void setActivityLabelAndIcon(IBinder token, CharSequence activityLabel,
- Bitmap activityBitmap) throws RemoteException;
+ public void setRecentsActivityValues(IBinder token, ActivityManager.RecentsActivityValues values)
+ throws RemoteException;
/*
* Private non-Binder interfaces
@@ -571,7 +567,7 @@
int MOVE_TASK_TO_BACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+24;
int MOVE_TASK_BACKWARDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+25;
int GET_TASK_FOR_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+26;
- int REPORT_THUMBNAIL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+27;
+
int GET_CONTENT_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+28;
int PUBLISH_CONTENT_PROVIDERS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+29;
int REF_CONTENT_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+30;
@@ -738,6 +734,6 @@
int START_LOCK_TASK_BY_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+214;
int STOP_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+215;
int IS_IN_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+216;
- int SET_ACTIVITY_LABEL_ICON_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+217;
+ int SET_RECENTS_ACTIVITY_VALUES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+217;
int START_VOICE_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+218;
}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index f290e94..fefba8a 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -101,7 +101,6 @@
Bundle coreSettings) throws RemoteException;
void scheduleExit() throws RemoteException;
void scheduleSuicide() throws RemoteException;
- void requestThumbnail(IBinder token) throws RemoteException;
void scheduleConfigurationChanged(Configuration config) throws RemoteException;
void updateTimeZone() throws RemoteException;
void clearDnsCache() throws RemoteException;
@@ -159,7 +158,7 @@
int SCHEDULE_STOP_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+11;
int BIND_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+12;
int SCHEDULE_EXIT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+13;
- int REQUEST_THUMBNAIL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+14;
+
int SCHEDULE_CONFIGURATION_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+15;
int SCHEDULE_SERVICE_ARGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+16;
int UPDATE_TIME_ZONE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+17;
diff --git a/core/java/android/app/IThumbnailReceiver.aidl b/core/java/android/app/IThumbnailReceiver.aidl
deleted file mode 100644
index 7943f2c..0000000
--- a/core/java/android/app/IThumbnailReceiver.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/* //device/java/android/android/app/IThumbnailReceiver.aidl
-**
-** Copyright 2006, 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.graphics.Bitmap;
-
-/**
- * System private API for receiving updated thumbnails from a checkpoint.
- *
- * {@hide}
- */
-oneway interface IThumbnailReceiver {
- void newThumbnail(int id, in Bitmap thumbnail, CharSequence description);
- void finished();
-}
-
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 6f68dfb..929bf65 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -173,12 +173,12 @@
public static final String ACTION_SET_NEW_PASSWORD
= "android.app.action.SET_NEW_PASSWORD";
/**
- * Flag for {@link #forwardMatchingIntents}: the intents will forwarded to the primary user.
+ * Flag for {@link #addForwardingIntentFilter}: the intents will forwarded to the primary user.
*/
public static int FLAG_TO_PRIMARY_USER = 0x0001;
/**
- * Flag for {@link #forwardMatchingIntents}: the intents will be forwarded to the managed
+ * Flag for {@link #addForwardingIntentFilter}: the intents will be forwarded to the managed
* profile.
*/
public static int FLAG_TO_MANAGED_PROFILE = 0x0002;
@@ -1949,10 +1949,10 @@
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param filter if an intent matches this IntentFilter, then it can be forwarded.
*/
- public void forwardMatchingIntents(ComponentName admin, IntentFilter filter, int flags) {
+ public void addForwardingIntentFilter(ComponentName admin, IntentFilter filter, int flags) {
if (mService != null) {
try {
- mService.forwardMatchingIntents(admin, filter, flags);
+ mService.addForwardingIntentFilter(admin, filter, flags);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -1960,7 +1960,7 @@
}
/**
- * Called by a profile owner to remove all the forwarding intent filters from the current user
+ * Called by a profile owner to remove the forwarding intent filters from the current user
* and from the owner.
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
*/
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 495a5f9..e3090b6 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -120,6 +120,6 @@
Bundle getApplicationRestrictions(in ComponentName who, in String packageName);
void setUserRestriction(in ComponentName who, in String key, boolean enable);
- void forwardMatchingIntents(in ComponentName admin, in IntentFilter filter, int flags);
+ void addForwardingIntentFilter(in ComponentName admin, in IntentFilter filter, int flags);
void clearForwardingIntentFilters(in ComponentName admin);
}
diff --git a/core/java/android/app/task/TaskParams.java b/core/java/android/app/task/TaskParams.java
index 429281c..e2eafd8 100644
--- a/core/java/android/app/task/TaskParams.java
+++ b/core/java/android/app/task/TaskParams.java
@@ -32,8 +32,7 @@
private final IBinder mCallback;
/**
- * @return The unique id of this task, specified at creation time using
- * {@link android.content.Task.Builder#Builder(int, Class)}.
+ * @return The unique id of this task, specified at creation time.
*/
public int getTaskId() {
return taskId;
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index dd3a871..d3e9089 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -181,7 +181,8 @@
* A bundle extra that hints to the AppWidgetProvider the category of host that owns this
* this widget. Can have the value {@link
* AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN} or {@link
- * AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}.
+ * AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD} or {@link
+ * AppWidgetProviderInfo#WIDGET_CATEGORY_RECENTS}.
*/
public static final String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory";
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 4b33799..8b9c7f0 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -54,6 +54,11 @@
public static final int WIDGET_CATEGORY_KEYGUARD = 2;
/**
+ * Indicates that the widget can be displayed within recents.
+ */
+ public static final int WIDGET_CATEGORY_RECENTS = 4;
+
+ /**
* Identity of this AppWidget component. This component should be a {@link
* android.content.BroadcastReceiver}, and it will be sent the AppWidget intents
* {@link android.appwidget as described in the AppWidget package documentation}.
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index a396a05..7f8d0ab 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -512,6 +512,25 @@
*/
public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
+ /**
+ * No preferrence of physical transport for GATT connections to remote dual-mode devices
+ * @hide
+ */
+ public static final int TRANSPORT_AUTO = 0;
+
+ /**
+ * Prefer BR/EDR transport for GATT connections to remote dual-mode devices
+ * @hide
+ */
+ public static final int TRANSPORT_BREDR = 1;
+
+ /**
+ * Prefer LE transport for GATT connections to remote dual-mode devices
+ * @hide
+ */
+ public static final int TRANSPORT_LE = 2;
+
+
/**
* Lazy initialization. Guaranteed final after first object constructed, or
* getService() called.
@@ -1216,6 +1235,27 @@
*/
public BluetoothGatt connectGatt(Context context, boolean autoConnect,
BluetoothGattCallback callback) {
+ return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO));
+ }
+
+ /**
+ * Connect to GATT Server hosted by this device. Caller acts as GATT client.
+ * The callback is used to deliver results to Caller, such as connection status as well
+ * as any further GATT client operations.
+ * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
+ * GATT client operations.
+ * @param callback GATT callback handler that will receive asynchronous callbacks.
+ * @param autoConnect Whether to directly connect to the remote device (false)
+ * or to automatically connect as soon as the remote
+ * device becomes available (true).
+ * @param transport preferred transport for GATT connections to remote dual-mode devices
+ * {@link BluetoothDevice#TRANSPORT_AUTO} or
+ * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
+ * @throws IllegalArgumentException if callback is null
+ * @hide
+ */
+ public BluetoothGatt connectGatt(Context context, boolean autoConnect,
+ BluetoothGattCallback callback, int transport) {
// TODO(Bluetooth) check whether platform support BLE
// Do the check here or in GattServer?
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -1226,10 +1266,11 @@
// BLE is not supported
return null;
}
- BluetoothGatt gatt = new BluetoothGatt(context, iGatt, this);
+ BluetoothGatt gatt = new BluetoothGatt(context, iGatt, this, transport);
gatt.connect(autoConnect, callback);
return gatt;
} catch (RemoteException e) {Log.e(TAG, "", e);}
return null;
}
+
}
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index ff3af7c..601d9ee 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -51,6 +51,7 @@
private int mConnState;
private final Object mStateLock = new Object();
private Boolean mDeviceBusy = false;
+ private int mTransport;
private static final int CONN_STATE_IDLE = 0;
private static final int CONN_STATE_CONNECTING = 1;
@@ -135,7 +136,7 @@
}
try {
mService.clientConnect(mClientIf, mDevice.getAddress(),
- !mAutoConnect); // autoConnect is inverse of "isDirect"
+ !mAutoConnect, mTransport); // autoConnect is inverse of "isDirect"
} catch (RemoteException e) {
Log.e(TAG,"",e);
}
@@ -600,10 +601,12 @@
}
};
- /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device) {
+ /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device,
+ int transport) {
mContext = context;
mService = iGatt;
mDevice = device;
+ mTransport = transport;
mServices = new ArrayList<BluetoothGattService>();
mConnState = CONN_STATE_IDLE;
@@ -759,7 +762,7 @@
public boolean connect() {
try {
mService.clientConnect(mClientIf, mDevice.getAddress(),
- false); // autoConnect is inverse of "isDirect"
+ false, mTransport); // autoConnect is inverse of "isDirect"
return true;
} catch (RemoteException e) {
Log.e(TAG,"",e);
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 0c00c06..34e8605 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -50,6 +50,7 @@
private Object mServerIfLock = new Object();
private int mServerIf;
+ private int mTransport;
private List<BluetoothGattService> mServices;
private static final int CALLBACK_REG_TIMEOUT = 10000;
@@ -269,12 +270,13 @@
/**
* Create a BluetoothGattServer proxy object.
*/
- /*package*/ BluetoothGattServer(Context context, IBluetoothGatt iGatt) {
+ /*package*/ BluetoothGattServer(Context context, IBluetoothGatt iGatt, int transport) {
mContext = context;
mService = iGatt;
mAdapter = BluetoothAdapter.getDefaultAdapter();
mCallback = null;
mServerIf = 0;
+ mTransport = transport;
mServices = new ArrayList<BluetoothGattService>();
}
@@ -401,7 +403,7 @@
try {
mService.serverConnect(mServerIf, device.getAddress(),
- autoConnect ? false : true); // autoConnect is inverse of "isDirect"
+ autoConnect ? false : true,mTransport); // autoConnect is inverse of "isDirect"
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index 172f3bc..b1618cf3 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -194,6 +194,26 @@
*/
public BluetoothGattServer openGattServer(Context context,
BluetoothGattServerCallback callback) {
+
+ return (openGattServer (context, callback, BluetoothDevice.TRANSPORT_AUTO));
+ }
+
+ /**
+ * Open a GATT Server
+ * The callback is used to deliver results to Caller, such as connection status as well
+ * as the results of any other GATT server operations.
+ * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
+ * to conduct GATT server operations.
+ * @param context App context
+ * @param callback GATT server callback handler that will receive asynchronous callbacks.
+ * @param transport preferred transport for GATT connections to remote dual-mode devices
+ * {@link BluetoothDevice#TRANSPORT_AUTO} or
+ * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
+ * @return BluetoothGattServer instance
+ * @hide
+ */
+ public BluetoothGattServer openGattServer(Context context,
+ BluetoothGattServerCallback callback,int transport) {
if (context == null || callback == null) {
throw new IllegalArgumentException("null parameter: " + context + " " + callback);
}
@@ -208,7 +228,7 @@
Log.e(TAG, "Fail to get GATT Server connection");
return null;
}
- BluetoothGattServer mGattServer = new BluetoothGattServer(context, iGatt);
+ BluetoothGattServer mGattServer = new BluetoothGattServer(context, iGatt,transport);
Boolean regStatus = mGattServer.registerCallback(callback);
return regStatus? mGattServer : null;
} catch (RemoteException e) {
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index f532f7c..00fd7ce 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -325,6 +325,7 @@
}
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ throw new IOException("unable to send RPC: " + e.getMessage());
}
}
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
index 6dd551e..a0b603e 100644
--- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -53,6 +53,9 @@
private static final boolean DBG = true;
private static final boolean VDBG = true;
+ // Event sent to the mBtdtHandler when DHCP fails so we can tear down the network.
+ private static final int EVENT_NETWORK_FAILED = 1;
+
private AtomicBoolean mTeardownRequested = new AtomicBoolean(false);
private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false);
private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
@@ -315,6 +318,7 @@
}
if (!success) {
Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
+ mBtdtHandler.obtainMessage(EVENT_NETWORK_FAILED).sendToTarget();
return;
}
mLinkProperties = dhcpResults.linkProperties;
@@ -407,6 +411,10 @@
if (VDBG) Log.d(TAG, "got EVENT_NETWORK_DISCONNECTED, " + linkProperties);
mBtdt.stopReverseTether();
break;
+ case EVENT_NETWORK_FAILED:
+ if (VDBG) Log.d(TAG, "got EVENT_NETWORK_FAILED");
+ mBtdt.teardown();
+ break;
}
}
}
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index 4b28516..ab53fb0 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -18,6 +18,8 @@
import android.os.ParcelUuid;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.HashSet;
import java.util.UUID;
@@ -76,6 +78,12 @@
public static final ParcelUuid BASE_UUID =
ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB");
+ /** Length of bytes for 16 bit UUID */
+ public static final int UUID_BYTES_16_BIT = 2;
+ /** Length of bytes for 32 bit UUID */
+ public static final int UUID_BYTES_32_BIT = 4;
+ /** Length of bytes for 128 bit UUID */
+ public static final int UUID_BYTES_128_BIT = 16;
public static final ParcelUuid[] RESERVED_UUIDS = {
AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget,
@@ -216,15 +224,60 @@
}
/**
+ * Parse UUID from bytes. The {@code uuidBytes} can represent a 16-bit, 32-bit or 128-bit UUID,
+ * but the returned UUID is always in 128-bit format.
+ * Note UUID is little endian in Bluetooth.
+ *
+ * @param uuidBytes Byte representation of uuid.
+ * @return {@link ParcelUuid} parsed from bytes.
+ * @throws IllegalArgumentException If the {@code uuidBytes} cannot be parsed.
+ */
+ public static ParcelUuid parseUuidFrom(byte[] uuidBytes) {
+ if (uuidBytes == null) {
+ throw new IllegalArgumentException("uuidBytes cannot be null");
+ }
+ int length = uuidBytes.length;
+ if (length != UUID_BYTES_16_BIT && length != UUID_BYTES_32_BIT &&
+ length != UUID_BYTES_128_BIT) {
+ throw new IllegalArgumentException("uuidBytes length invalid - " + length);
+ }
+
+ // Construct a 128 bit UUID.
+ if (length == UUID_BYTES_128_BIT) {
+ ByteBuffer buf = ByteBuffer.wrap(uuidBytes).order(ByteOrder.LITTLE_ENDIAN);
+ long msb = buf.getLong(8);
+ long lsb = buf.getLong(0);
+ return new ParcelUuid(new UUID(msb, lsb));
+ }
+
+ // For 16 bit and 32 bit UUID we need to convert them to 128 bit value.
+ // 128_bit_value = uuid * 2^96 + BASE_UUID
+ long shortUuid;
+ if (length == UUID_BYTES_16_BIT) {
+ shortUuid = uuidBytes[0] & 0xFF;
+ shortUuid += (uuidBytes[1] & 0xFF) << 8;
+ } else {
+ shortUuid = uuidBytes[0] & 0xFF ;
+ shortUuid += (uuidBytes[1] & 0xFF) << 8;
+ shortUuid += (uuidBytes[2] & 0xFF) << 16;
+ shortUuid += (uuidBytes[3] & 0xFF) << 24;
+ }
+ long msb = BASE_UUID.getUuid().getMostSignificantBits() + (shortUuid << 32);
+ long lsb = BASE_UUID.getUuid().getLeastSignificantBits();
+ return new ParcelUuid(new UUID(msb, lsb));
+ }
+
+ /**
* Check whether the given parcelUuid can be converted to 16 bit bluetooth uuid.
+ *
* @param parcelUuid
* @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise.
*/
public static boolean isShortUuid(ParcelUuid parcelUuid) {
- UUID uuid = parcelUuid.getUuid();
- if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) {
- return false;
- }
- return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L);
+ UUID uuid = parcelUuid.getUuid();
+ if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) {
+ return false;
+ }
+ return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L);
}
}
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index c6b5c3d..49b156d 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -35,7 +35,7 @@
void registerClient(in ParcelUuid appId, in IBluetoothGattCallback callback);
void unregisterClient(in int clientIf);
- void clientConnect(in int clientIf, in String address, in boolean isDirect);
+ void clientConnect(in int clientIf, in String address, in boolean isDirect, in int transport);
void clientDisconnect(in int clientIf, in String address);
void startAdvertising(in int appIf);
void stopAdvertising();
@@ -77,7 +77,7 @@
void registerServer(in ParcelUuid appId, in IBluetoothGattServerCallback callback);
void unregisterServer(in int serverIf);
- void serverConnect(in int servertIf, in String address, in boolean isDirect);
+ void serverConnect(in int servertIf, in String address, in boolean isDirect, in int transport);
void serverDisconnect(in int serverIf, in String address);
void beginServiceDeclaration(in int serverIf, in int srvcType,
in int srvcInstanceId, in int minHandles,
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index de223a3..7c625bd 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2377,6 +2377,16 @@
/**
* Use with {@link #getSystemService} to retrieve a
+ * {@link android.service.fingerprint.FingerprintManager} for handling management
+ * of fingerprints.
+ *
+ * @see #getSystemService
+ * @see android.app.FingerprintManager
+ */
+ public static final String FINGERPRINT_SERVICE = "fingerprint";
+
+ /**
+ * Use with {@link #getSystemService} to retrieve a
* {@link android.media.MediaRouter} for controlling and managing
* routing of media.
*
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index cf9a296..03eb50f 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -247,7 +247,8 @@
void clearPackagePersistentPreferredActivities(String packageName, int userId);
- void addForwardingIntentFilter(in IntentFilter filter, int userIdOrig, int userIdDest);
+ void addForwardingIntentFilter(in IntentFilter filter, boolean removable, int userIdOrig,
+ int userIdDest);
void clearForwardingIntentFilters(int userIdOrig);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 484a2a1..1a003ff 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3507,4 +3507,26 @@
return Environment.getDataDirectory().toString() + "/user/" + userId
+ "/" + packageName;
}
+
+ /**
+ * Adds a forwarding intent filter. After calling this method all intents sent from the user
+ * with id userIdOrig can also be be resolved by activities in the user with id userIdDest if
+ * they match the specified intent filter.
+ * @param filter the {@link IntentFilter} the intent has to match to be forwarded
+ * @param removable if set to false, {@link clearForwardingIntents} will not remove this intent
+ * filter
+ * @param userIdOrig user from which the intent can be forwarded
+ * @param userIdDest user to which the intent can be forwarded
+ * @hide
+ */
+ public abstract void addForwardingIntentFilter(IntentFilter filter, boolean removable,
+ int userIdOrig, int userIdDest);
+
+ /**
+ * Clearing all removable {@link ForwardingIntentFilter}s that are set with the given user as
+ * the origin.
+ * @param userIdOrig user from which the intent can be forwarded
+ * @hide
+ */
+ public abstract void clearForwardingIntentFilters(int userIdOrig);
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 1331777..499de17 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -137,45 +137,42 @@
/**
* 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 int selectDefaultTheme(int curTheme, int targetSdkVersion) {
+ public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
return selectSystemTheme(curTheme, targetSdkVersion,
- com.android.internal.R.array.system_theme_sdks,
- com.android.internal.R.array.system_theme_styles);
+ 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_Light_DarkActionBar);
}
- /**
- * Returns the most appropriate default theme for the specified target SDK version.
- *
- * @param curTheme The current theme, or 0 if not specified.
- * @param targetSdkVersion The target SDK version.
- * @param sdkArrayId Identifier for integer array resource containing
- * sorted minimum SDK versions. First entry must be 0.
- * @param themeArrayId Identifier for array resource containing the
- * default themes that map to SDK versions.
- * @return A theme resource identifier
- * @hide
- */
- public int selectSystemTheme(
- int curTheme, int targetSdkVersion, int sdkArrayId, int themeArrayId) {
+ /** @hide */
+ public static int selectSystemTheme(int curTheme, int targetSdkVersion, int orig, int holo,
+ int dark, int deviceDefault) {
if (curTheme != 0) {
return curTheme;
}
-
- final int[] targetSdks = getIntArray(sdkArrayId);
- final TypedArray defaultThemes = obtainTypedArray(themeArrayId);
- for (int i = targetSdks.length - 1; i > 0; i--) {
- if (targetSdkVersion >= targetSdks[i]) {
- return defaultThemes.getResourceId(i, 0);
- }
+ if (targetSdkVersion < Build.VERSION_CODES.HONEYCOMB) {
+ return orig;
}
-
- return defaultThemes.getResourceId(0, 0);
+ if (targetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ return holo;
+ }
+ if (targetSdkVersion < Build.VERSION_CODES.CUR_DEVELOPMENT) {
+ return dark;
+ }
+ return deviceDefault;
}
/**
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 722d956..28309d7 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -372,7 +372,6 @@
/**
* <p>Optional. Hyperfocal distance for this lens.</p>
- * <p>If the lens is fixed focus, the camera device will report 0.</p>
* <p>If the lens is not fixed focus, the camera device will report this
* field when {@link CameraCharacteristics#LENS_INFO_FOCUS_DISTANCE_CALIBRATION android.lens.info.focusDistanceCalibration} is APPROXIMATE or CALIBRATED.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index bb290af..9d0e0e1 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -192,8 +192,9 @@
*
* <p>The camera device will query each Surface's size and formats upon this
* call, so they must be set to a valid setting at this time (in particular:
- * if the format is user-visible, it must be one of android.scaler.availableFormats;
- * and the size must be one of android.scaler.available[Processed|Jpeg]Sizes).</p>
+ * if the format is user-visible, it must be one of
+ * {@link StreamConfigurationMap#getOutputFormats}; and the size must be one of
+ * {@link StreamConfigurationMap#getOutputSizes(int)}).</p>
*
* <p>When this method is called with valid Surfaces, the device will transition to the {@link
* StateListener#onBusy busy state}. Once configuration is complete, the device will transition
@@ -239,6 +240,9 @@
* @see StateListener#onUnconfigured
* @see #stopRepeating
* @see #flush
+ * @see StreamConfigurationMap#getOutputFormats()
+ * @see StreamConfigurationMap#getOutputSizes(int)
+ * @see StreamConfigurationMap#getOutputSizes(Class)
*/
public void configureOutputs(List<Surface> outputs) throws CameraAccessException;
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index ba8db3a..6e38a22f 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -1295,6 +1295,20 @@
public static final int CONTROL_SCENE_MODE_BARCODE = 16;
//
+ // Enumeration values for CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
+ //
+
+ /**
+ * @see CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
+ */
+ public static final int CONTROL_VIDEO_STABILIZATION_MODE_OFF = 0;
+
+ /**
+ * @see CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
+ */
+ public static final int CONTROL_VIDEO_STABILIZATION_MODE_ON = 1;
+
+ //
// Enumeration values for CaptureRequest#EDGE_MODE
//
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index c4e342c..f161f3a 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -831,9 +831,11 @@
* stabilized</p>
*
* @see CaptureRequest#SCALER_CROP_REGION
+ * @see #CONTROL_VIDEO_STABILIZATION_MODE_OFF
+ * @see #CONTROL_VIDEO_STABILIZATION_MODE_ON
*/
- public static final Key<Boolean> CONTROL_VIDEO_STABILIZATION_MODE =
- new Key<Boolean>("android.control.videoStabilizationMode", boolean.class);
+ public static final Key<Integer> CONTROL_VIDEO_STABILIZATION_MODE =
+ new Key<Integer>("android.control.videoStabilizationMode", int.class);
/**
* <p>Operation mode for edge
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index d8981c8..1d2d0e9 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -124,6 +124,58 @@
/**
+ * <p>The mode control selects how the image data is converted from the
+ * sensor's native color into linear sRGB color.</p>
+ * <p>When auto-white balance is enabled with {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, this
+ * control is overridden by the AWB routine. When AWB is disabled, the
+ * application controls how the color mapping is performed.</p>
+ * <p>We define the expected processing pipeline below. For consistency
+ * across devices, this is always the case with TRANSFORM_MATRIX.</p>
+ * <p>When either FULL or HIGH_QUALITY is used, the camera device may
+ * do additional processing but {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} and
+ * {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform} will still be provided by the
+ * camera device (in the results) and be roughly correct.</p>
+ * <p>Switching to TRANSFORM_MATRIX and using the data provided from
+ * FAST or HIGH_QUALITY will yield a picture with the same white point
+ * as what was produced by the camera device in the earlier frame.</p>
+ * <p>The expected processing pipeline is as follows:</p>
+ * <p><img alt="White balance processing pipeline" src="../../../../images/camera2/metadata/android.colorCorrection.mode/processing_pipeline.png" /></p>
+ * <p>The white balance is encoded by two values, a 4-channel white-balance
+ * gain vector (applied in the Bayer domain), and a 3x3 color transform
+ * matrix (applied after demosaic).</p>
+ * <p>The 4-channel white-balance gains are defined as:</p>
+ * <pre><code>{@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} = [ R G_even G_odd B ]
+ * </code></pre>
+ * <p>where <code>G_even</code> is the gain for green pixels on even rows of the
+ * output, and <code>G_odd</code> is the gain for green pixels on the odd rows.
+ * These may be identical for a given camera device implementation; if
+ * the camera device does not support a separate gain for even/odd green
+ * channels, it will use the <code>G_even</code> value, and write <code>G_odd</code> equal to
+ * <code>G_even</code> in the output result metadata.</p>
+ * <p>The matrices for color transforms are defined as a 9-entry vector:</p>
+ * <pre><code>{@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform} = [ I0 I1 I2 I3 I4 I5 I6 I7 I8 ]
+ * </code></pre>
+ * <p>which define a transform from input sensor colors, <code>P_in = [ r g b ]</code>,
+ * to output linear sRGB, <code>P_out = [ r' g' b' ]</code>,</p>
+ * <p>with colors as follows:</p>
+ * <pre><code>r' = I0r + I1g + I2b
+ * g' = I3r + I4g + I5b
+ * b' = I6r + I7g + I8b
+ * </code></pre>
+ * <p>Both the input and output value ranges must match. Overflow/underflow
+ * values are clipped to fit within the range.</p>
+ *
+ * @see CaptureRequest#COLOR_CORRECTION_GAINS
+ * @see CaptureRequest#COLOR_CORRECTION_TRANSFORM
+ * @see CaptureRequest#CONTROL_AWB_MODE
+ * @see #COLOR_CORRECTION_MODE_TRANSFORM_MATRIX
+ * @see #COLOR_CORRECTION_MODE_FAST
+ * @see #COLOR_CORRECTION_MODE_HIGH_QUALITY
+ */
+ public static final Key<Integer> COLOR_CORRECTION_MODE =
+ new Key<Integer>("android.colorCorrection.mode", int.class);
+
+ /**
* <p>A color transform matrix to use to transform
* from sensor RGB color space to output linear sRGB color space</p>
* <p>This matrix is either set by the camera device when the request
@@ -176,6 +228,82 @@
new Key<Integer>("android.control.aePrecaptureId", int.class);
/**
+ * <p>The desired setting for the camera device's auto-exposure
+ * algorithm's antibanding compensation.</p>
+ * <p>Some kinds of lighting fixtures, such as some fluorescent
+ * lights, flicker at the rate of the power supply frequency
+ * (60Hz or 50Hz, depending on country). While this is
+ * typically not noticeable to a person, it can be visible to
+ * a camera device. If a camera sets its exposure time to the
+ * wrong value, the flicker may become visible in the
+ * viewfinder as flicker or in a final captured image, as a
+ * set of variable-brightness bands across the image.</p>
+ * <p>Therefore, the auto-exposure routines of camera devices
+ * include antibanding routines that ensure that the chosen
+ * exposure value will not cause such banding. The choice of
+ * exposure time depends on the rate of flicker, which the
+ * camera device can detect automatically, or the expected
+ * rate can be selected by the application using this
+ * control.</p>
+ * <p>A given camera device may not support all of the possible
+ * options for the antibanding mode. The
+ * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_ANTIBANDING_MODES android.control.aeAvailableAntibandingModes} key contains
+ * the available modes for a given camera device.</p>
+ * <p>The default mode is AUTO, which must be supported by all
+ * camera devices.</p>
+ * <p>If manual exposure control is enabled (by setting
+ * {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} or {@link CaptureRequest#CONTROL_MODE android.control.mode} to OFF),
+ * then this setting has no effect, and the application must
+ * ensure it selects exposure times that do not cause banding
+ * issues. The {@link CaptureResult#STATISTICS_SCENE_FLICKER android.statistics.sceneFlicker} key can assist
+ * the application in this.</p>
+ *
+ * @see CameraCharacteristics#CONTROL_AE_AVAILABLE_ANTIBANDING_MODES
+ * @see CaptureRequest#CONTROL_AE_MODE
+ * @see CaptureRequest#CONTROL_MODE
+ * @see CaptureResult#STATISTICS_SCENE_FLICKER
+ * @see #CONTROL_AE_ANTIBANDING_MODE_OFF
+ * @see #CONTROL_AE_ANTIBANDING_MODE_50HZ
+ * @see #CONTROL_AE_ANTIBANDING_MODE_60HZ
+ * @see #CONTROL_AE_ANTIBANDING_MODE_AUTO
+ */
+ public static final Key<Integer> CONTROL_AE_ANTIBANDING_MODE =
+ new Key<Integer>("android.control.aeAntibandingMode", int.class);
+
+ /**
+ * <p>Adjustment to AE target image
+ * brightness</p>
+ * <p>For example, if EV step is 0.333, '6' will mean an
+ * exposure compensation of +2 EV; -3 will mean an exposure
+ * compensation of -1</p>
+ */
+ public static final Key<Integer> CONTROL_AE_EXPOSURE_COMPENSATION =
+ new Key<Integer>("android.control.aeExposureCompensation", int.class);
+
+ /**
+ * <p>Whether AE is currently locked to its latest
+ * calculated values.</p>
+ * <p>Note that even when AE is locked, the flash may be
+ * fired if the {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_AUTO_FLASH / ON_ALWAYS_FLASH /
+ * ON_AUTO_FLASH_REDEYE.</p>
+ * <p>If AE precapture is triggered (see {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger})
+ * when AE is already locked, the camera device will not change the exposure time
+ * ({@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}) and sensitivity ({@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity})
+ * parameters. The flash may be fired if the {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode}
+ * is ON_AUTO_FLASH/ON_AUTO_FLASH_REDEYE and the scene is too dark. If the
+ * {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is ON_ALWAYS_FLASH, the scene may become overexposed.</p>
+ * <p>See {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE lock related state transition details.</p>
+ *
+ * @see CaptureRequest#CONTROL_AE_MODE
+ * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
+ * @see CaptureResult#CONTROL_AE_STATE
+ * @see CaptureRequest#SENSOR_EXPOSURE_TIME
+ * @see CaptureRequest#SENSOR_SENSITIVITY
+ */
+ public static final Key<Boolean> CONTROL_AE_LOCK =
+ new Key<Boolean>("android.control.aeLock", boolean.class);
+
+ /**
* <p>The desired mode for the camera device's
* auto-exposure routine.</p>
* <p>This control is only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} is
@@ -237,6 +365,35 @@
new Key<int[]>("android.control.aeRegions", int[].class);
/**
+ * <p>Range over which fps can be adjusted to
+ * maintain exposure</p>
+ * <p>Only constrains AE algorithm, not manual control
+ * of {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}</p>
+ *
+ * @see CaptureRequest#SENSOR_EXPOSURE_TIME
+ */
+ public static final Key<int[]> CONTROL_AE_TARGET_FPS_RANGE =
+ new Key<int[]>("android.control.aeTargetFpsRange", int[].class);
+
+ /**
+ * <p>Whether the camera device will trigger a precapture
+ * metering sequence when it processes this request.</p>
+ * <p>This entry is normally set to IDLE, or is not
+ * included at all in the request settings. When included and
+ * set to START, the camera device will trigger the autoexposure
+ * precapture metering sequence.</p>
+ * <p>The effect of AE precapture trigger depends on the current
+ * AE mode and state; see {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE precapture
+ * state transition details.</p>
+ *
+ * @see CaptureResult#CONTROL_AE_STATE
+ * @see #CONTROL_AE_PRECAPTURE_TRIGGER_IDLE
+ * @see #CONTROL_AE_PRECAPTURE_TRIGGER_START
+ */
+ public static final Key<Integer> CONTROL_AE_PRECAPTURE_TRIGGER =
+ new Key<Integer>("android.control.aePrecaptureTrigger", int.class);
+
+ /**
* <p>Current state of AE algorithm</p>
* <p>Switching between or enabling AE modes ({@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode}) always
* resets the AE state to INACTIVE. Similarly, switching between {@link CaptureRequest#CONTROL_MODE android.control.mode},
@@ -481,6 +638,24 @@
new Key<int[]>("android.control.afRegions", int[].class);
/**
+ * <p>Whether the camera device will trigger autofocus for this request.</p>
+ * <p>This entry is normally set to IDLE, or is not
+ * included at all in the request settings.</p>
+ * <p>When included and set to START, the camera device will trigger the
+ * autofocus algorithm. If autofocus is disabled, this trigger has no effect.</p>
+ * <p>When set to CANCEL, the camera device will cancel any active trigger,
+ * and return to its initial AF state.</p>
+ * <p>See {@link CaptureResult#CONTROL_AF_STATE android.control.afState} for what that means for each AF mode.</p>
+ *
+ * @see CaptureResult#CONTROL_AF_STATE
+ * @see #CONTROL_AF_TRIGGER_IDLE
+ * @see #CONTROL_AF_TRIGGER_START
+ * @see #CONTROL_AF_TRIGGER_CANCEL
+ */
+ public static final Key<Integer> CONTROL_AF_TRIGGER =
+ new Key<Integer>("android.control.afTrigger", int.class);
+
+ /**
* <p>Current state of AF algorithm.</p>
* <p>Switching between or enabling AF modes ({@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}) always
* resets the AF state to INACTIVE. Similarly, switching between {@link CaptureRequest#CONTROL_MODE android.control.mode},
@@ -889,6 +1064,16 @@
new Key<Integer>("android.control.afTriggerId", int.class);
/**
+ * <p>Whether AWB is currently locked to its
+ * latest calculated values.</p>
+ * <p>Note that AWB lock is only meaningful for AUTO
+ * mode; in other modes, AWB is already fixed to a specific
+ * setting.</p>
+ */
+ public static final Key<Boolean> CONTROL_AWB_LOCK =
+ new Key<Boolean>("android.control.awbLock", boolean.class);
+
+ /**
* <p>Whether AWB is currently setting the color
* transform fields, and what its illumination target
* is.</p>
@@ -948,6 +1133,30 @@
new Key<int[]>("android.control.awbRegions", int[].class);
/**
+ * <p>Information to the camera device 3A (auto-exposure,
+ * auto-focus, auto-white balance) routines about the purpose
+ * of this capture, to help the camera device to decide optimal 3A
+ * strategy.</p>
+ * <p>This control (except for MANUAL) is only effective if
+ * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
+ * <p>ZERO_SHUTTER_LAG must be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+ * contains ZSL. MANUAL must be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+ * contains MANUAL_SENSOR.</p>
+ *
+ * @see CaptureRequest#CONTROL_MODE
+ * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+ * @see #CONTROL_CAPTURE_INTENT_CUSTOM
+ * @see #CONTROL_CAPTURE_INTENT_PREVIEW
+ * @see #CONTROL_CAPTURE_INTENT_STILL_CAPTURE
+ * @see #CONTROL_CAPTURE_INTENT_VIDEO_RECORD
+ * @see #CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT
+ * @see #CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG
+ * @see #CONTROL_CAPTURE_INTENT_MANUAL
+ */
+ public static final Key<Integer> CONTROL_CAPTURE_INTENT =
+ new Key<Integer>("android.control.captureIntent", int.class);
+
+ /**
* <p>Current state of AWB algorithm</p>
* <p>Switching between or enabling AWB modes ({@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}) always
* resets the AWB state to INACTIVE. Similarly, switching between {@link CaptureRequest#CONTROL_MODE android.control.mode},
@@ -1078,6 +1287,31 @@
new Key<Integer>("android.control.awbState", int.class);
/**
+ * <p>A special color effect to apply.</p>
+ * <p>When this mode is set, a color effect will be applied
+ * to images produced by the camera device. The interpretation
+ * and implementation of these color effects is left to the
+ * implementor of the camera device, and should not be
+ * depended on to be consistent (or present) across all
+ * devices.</p>
+ * <p>A color effect will only be applied if
+ * {@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF.</p>
+ *
+ * @see CaptureRequest#CONTROL_MODE
+ * @see #CONTROL_EFFECT_MODE_OFF
+ * @see #CONTROL_EFFECT_MODE_MONO
+ * @see #CONTROL_EFFECT_MODE_NEGATIVE
+ * @see #CONTROL_EFFECT_MODE_SOLARIZE
+ * @see #CONTROL_EFFECT_MODE_SEPIA
+ * @see #CONTROL_EFFECT_MODE_POSTERIZE
+ * @see #CONTROL_EFFECT_MODE_WHITEBOARD
+ * @see #CONTROL_EFFECT_MODE_BLACKBOARD
+ * @see #CONTROL_EFFECT_MODE_AQUA
+ */
+ public static final Key<Integer> CONTROL_EFFECT_MODE =
+ new Key<Integer>("android.control.effectMode", int.class);
+
+ /**
* <p>Overall mode of 3A control
* routines.</p>
* <p>High-level 3A control. When set to OFF, all 3A control
@@ -1106,6 +1340,57 @@
new Key<Integer>("android.control.mode", int.class);
/**
+ * <p>A camera mode optimized for conditions typical in a particular
+ * capture setting.</p>
+ * <p>This is the mode that that is active when
+ * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code>. Aside from FACE_PRIORITY,
+ * these modes will disable {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode},
+ * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode} while in use.</p>
+ * <p>The interpretation and implementation of these scene modes is left
+ * to the implementor of the camera device. Their behavior will not be
+ * consistent across all devices, and any given device may only implement
+ * a subset of these modes.</p>
+ *
+ * @see CaptureRequest#CONTROL_AE_MODE
+ * @see CaptureRequest#CONTROL_AF_MODE
+ * @see CaptureRequest#CONTROL_AWB_MODE
+ * @see CaptureRequest#CONTROL_MODE
+ * @see #CONTROL_SCENE_MODE_DISABLED
+ * @see #CONTROL_SCENE_MODE_FACE_PRIORITY
+ * @see #CONTROL_SCENE_MODE_ACTION
+ * @see #CONTROL_SCENE_MODE_PORTRAIT
+ * @see #CONTROL_SCENE_MODE_LANDSCAPE
+ * @see #CONTROL_SCENE_MODE_NIGHT
+ * @see #CONTROL_SCENE_MODE_NIGHT_PORTRAIT
+ * @see #CONTROL_SCENE_MODE_THEATRE
+ * @see #CONTROL_SCENE_MODE_BEACH
+ * @see #CONTROL_SCENE_MODE_SNOW
+ * @see #CONTROL_SCENE_MODE_SUNSET
+ * @see #CONTROL_SCENE_MODE_STEADYPHOTO
+ * @see #CONTROL_SCENE_MODE_FIREWORKS
+ * @see #CONTROL_SCENE_MODE_SPORTS
+ * @see #CONTROL_SCENE_MODE_PARTY
+ * @see #CONTROL_SCENE_MODE_CANDLELIGHT
+ * @see #CONTROL_SCENE_MODE_BARCODE
+ */
+ public static final Key<Integer> CONTROL_SCENE_MODE =
+ new Key<Integer>("android.control.sceneMode", int.class);
+
+ /**
+ * <p>Whether video stabilization is
+ * active</p>
+ * <p>If enabled, video stabilization can modify the
+ * {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to keep the video stream
+ * stabilized</p>
+ *
+ * @see CaptureRequest#SCALER_CROP_REGION
+ * @see #CONTROL_VIDEO_STABILIZATION_MODE_OFF
+ * @see #CONTROL_VIDEO_STABILIZATION_MODE_ON
+ */
+ public static final Key<Integer> CONTROL_VIDEO_STABILIZATION_MODE =
+ new Key<Integer>("android.control.videoStabilizationMode", int.class);
+
+ /**
* <p>Operation mode for edge
* enhancement.</p>
* <p>Edge/sharpness/detail enhancement. OFF means no
@@ -1688,6 +1973,22 @@
new Key<Float>("android.sensor.greenSplit", float.class);
/**
+ * <p>A pixel <code>[R, G_even, G_odd, B]</code> that supplies the test pattern
+ * when {@link CaptureRequest#SENSOR_TEST_PATTERN_MODE android.sensor.testPatternMode} is SOLID_COLOR.</p>
+ * <p>Each color channel is treated as an unsigned 32-bit integer.
+ * The camera device then uses the most significant X bits
+ * that correspond to how many bits are in its Bayer raw sensor
+ * output.</p>
+ * <p>For example, a sensor with RAW10 Bayer output would use the
+ * 10 most significant bits from each color channel.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ *
+ * @see CaptureRequest#SENSOR_TEST_PATTERN_MODE
+ */
+ public static final Key<int[]> SENSOR_TEST_PATTERN_DATA =
+ new Key<int[]>("android.sensor.testPatternData", int[].class);
+
+ /**
* <p>When enabled, the sensor sends a test pattern instead of
* doing a real exposure from the camera.</p>
* <p>When a test pattern is enabled, all manual sensor controls specified
@@ -1936,6 +2237,20 @@
new Key<int[]>("android.statistics.hotPixelMap", int[].class);
/**
+ * <p>Whether the camera device will output the lens
+ * shading map in output result metadata.</p>
+ * <p>When set to ON,
+ * {@link CaptureResult#STATISTICS_LENS_SHADING_MAP android.statistics.lensShadingMap} must be provided in
+ * the output result metadata.</p>
+ *
+ * @see CaptureResult#STATISTICS_LENS_SHADING_MAP
+ * @see #STATISTICS_LENS_SHADING_MAP_MODE_OFF
+ * @see #STATISTICS_LENS_SHADING_MAP_MODE_ON
+ */
+ public static final Key<Integer> STATISTICS_LENS_SHADING_MAP_MODE =
+ new Key<Integer>("android.statistics.lensShadingMapMode", int.class);
+
+ /**
* <p>Tonemapping / contrast / gamma curve for the blue
* channel, to use when {@link CaptureRequest#TONEMAP_MODE android.tonemap.mode} is
* CONTRAST_CURVE.</p>
diff --git a/core/java/android/hardware/camera2/ColorSpaceTransform.java b/core/java/android/hardware/camera2/ColorSpaceTransform.java
new file mode 100644
index 0000000..9912e4b
--- /dev/null
+++ b/core/java/android/hardware/camera2/ColorSpaceTransform.java
@@ -0,0 +1,239 @@
+/*
+ * 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.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+import java.util.Arrays;
+
+/**
+ * Immutable class for describing a 3x3 matrix of {@link Rational} values in row-major order.
+ *
+ * <p>This matrix maps a transform from one color space to another. For the particular color space
+ * source and target, see the appropriate camera metadata documentation for the key that provides
+ * this value.</p>
+ *
+ * @see CameraMetadata
+ */
+public final class ColorSpaceTransform {
+
+ /** The number of rows in this matrix. */
+ private static final int ROWS = 3;
+
+ /** The number of columns in this matrix. */
+ private static final int COLUMNS = 3;
+
+ /** The number of total Rational elements in this matrix. */
+ private static final int COUNT = ROWS * COLUMNS;
+
+ /** Number of int elements in a rational. */
+ private static final int RATIONAL_SIZE = 2;
+
+ /** Numerator offset inside a rational (pair). */
+ private static final int OFFSET_NUMERATOR = 0;
+
+ /** Denominator offset inside a rational (pair). */
+ private static final int OFFSET_DENOMINATOR = 1;
+
+ /** Number of int elements in this matrix. */
+ private static final int COUNT_INT = ROWS * COLUMNS * RATIONAL_SIZE;
+
+ /**
+ * Create a new immutable {@link ColorSpaceTransform} instance from a {@link Rational} array.
+ *
+ * <p>The elements must be stored in a row-major order.</p>
+ *
+ * @param elements An array of {@code 9} elements
+ *
+ * @throws IllegalArgumentException
+ * if the count of {@code elements} is not {@code 9}
+ * @throws NullPointerException
+ * if {@code elements} or any sub-element is {@code null}
+ */
+ public ColorSpaceTransform(Rational[] elements) {
+
+ checkNotNull(elements, "elements must not be null");
+ if (elements.length != COUNT) {
+ throw new IllegalArgumentException("elements must be " + COUNT + " length");
+ }
+
+ mElements = new int[COUNT_INT];
+
+ for (int i = 0; i < elements.length; ++i) {
+ checkNotNull(elements, "element[" + i + "] must not be null");
+ mElements[i * RATIONAL_SIZE + OFFSET_NUMERATOR] = elements[i].getNumerator();
+ mElements[i * RATIONAL_SIZE + OFFSET_DENOMINATOR] = elements[i].getDenominator();
+ }
+ }
+
+ /**
+ * Create a new immutable {@link ColorSpaceTransform} instance from an {@code int} array.
+ *
+ * <p>The elements must be stored in a row-major order. Each rational is stored
+ * contiguously as a {@code (numerator, denominator)} pair.</p>
+ *
+ * <p>In particular:<pre>{@code
+ * int[] elements = new int[
+ * N11, D11, N12, D12, N13, D13,
+ * N21, D21, N22, D22, N23, D23,
+ * N31, D31, N32, D32, N33, D33
+ * ];
+ *
+ * new ColorSpaceTransform(elements)}</pre>
+ *
+ * where {@code Nij} and {@code Dij} is the numerator and denominator for row {@code i} and
+ * column {@code j}.</p>
+ *
+ * @param elements An array of {@code 18} elements
+ *
+ * @throws IllegalArgumentException
+ * if the count of {@code elements} is not {@code 18}
+ * @throws NullPointerException
+ * if {@code elements} is {@code null}
+ */
+ public ColorSpaceTransform(int[] elements) {
+ checkNotNull(elements, "elements must not be null");
+ if (elements.length != COUNT_INT) {
+ throw new IllegalArgumentException("elements must be " + COUNT_INT + " length");
+ }
+
+ for (int i = 0; i < elements.length; ++i) {
+ checkNotNull(elements, "element " + i + " must not be null");
+ }
+
+ mElements = Arrays.copyOf(elements, elements.length);
+ }
+
+ /**
+ * Get an element of this matrix by its row and column.
+ *
+ * <p>The rows must be within the range [0, 3),
+ * and the column must be within the range [0, 3).</p>
+ *
+ * @return element (non-{@code null})
+ *
+ * @throws IllegalArgumentException if column or row was out of range
+ */
+ public Rational getElement(int column, int row) {
+ if (column < 0 || column >= COLUMNS) {
+ throw new IllegalArgumentException("column out of range");
+ } else if (row < 0 || row >= ROWS) {
+ throw new IllegalArgumentException("row out of range");
+ }
+
+ int numerator = mElements[row * ROWS * RATIONAL_SIZE + column + OFFSET_NUMERATOR];
+ int denominator = mElements[row * ROWS * RATIONAL_SIZE + column + OFFSET_DENOMINATOR];
+
+ return new Rational(numerator, denominator);
+ }
+
+ /**
+ * Copy the {@link Rational} elements in row-major order from this matrix into the destination.
+ *
+ * @param destination
+ * an array big enough to hold at least {@code 9} elements after the
+ * {@code offset}
+ * @param offset
+ * a non-negative offset into the array
+ * @throws NullPointerException
+ * If {@code destination} was {@code null}
+ * @throws ArrayIndexOutOfBoundsException
+ * If there's not enough room to write the elements at the specified destination and
+ * offset.
+ */
+ public void copyElements(Rational[] destination, int offset) {
+ checkArgumentNonnegative(offset, "offset must not be negative");
+ checkNotNull(destination, "destination must not be null");
+ if (destination.length + offset < COUNT) {
+ throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
+ }
+
+ for (int i = 0, j = 0; i < COUNT; ++i, j += RATIONAL_SIZE) {
+ int numerator = mElements[j + OFFSET_NUMERATOR];
+ int denominator = mElements[j + OFFSET_DENOMINATOR];
+
+ destination[i + offset] = new Rational(numerator, denominator);
+ }
+ }
+
+ /**
+ * Copy the {@link Rational} elements in row-major order from this matrix into the destination.
+ *
+ * <p>Each element is stored as a contiguous rational packed as a
+ * {@code (numerator, denominator)} pair of ints, identical to the
+ * {@link ColorSpaceTransform#ColorSpaceTransform(int[]) constructor}.</p>
+ *
+ * @param destination
+ * an array big enough to hold at least {@code 18} elements after the
+ * {@code offset}
+ * @param offset
+ * a non-negative offset into the array
+ * @throws NullPointerException
+ * If {@code destination} was {@code null}
+ * @throws ArrayIndexOutOfBoundsException
+ * If there's not enough room to write the elements at the specified destination and
+ * offset.
+ *
+ * @see ColorSpaceTransform#ColorSpaceTransform(int[])
+ */
+ public void copyElements(int[] destination, int offset) {
+ checkArgumentNonnegative(offset, "offset must not be negative");
+ checkNotNull(destination, "destination must not be null");
+ if (destination.length + offset < COUNT_INT) {
+ throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
+ }
+
+ // Manual copy faster than System#arraycopy for very small loops
+ for (int i = 0; i < COUNT_INT; ++i) {
+ destination[i + offset] = mElements[i];
+ }
+ }
+
+ /**
+ * Check if this {@link ColorSpaceTransform} is equal to another {@link ColorSpaceTransform}.
+ *
+ * <p>Two color space transforms are equal if and only if all of their elements are
+ * {@link Object#equals equal}.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ColorSpaceTransform) {
+ final ColorSpaceTransform other = (ColorSpaceTransform) obj;
+ return Arrays.equals(mElements, other.mElements);
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return HashCodeHelpers.hashCode(mElements);
+ }
+
+ private final int[] mElements;
+};
diff --git a/core/java/android/hardware/camera2/LensShadingMap.java b/core/java/android/hardware/camera2/LensShadingMap.java
new file mode 100644
index 0000000..2c224f6
--- /dev/null
+++ b/core/java/android/hardware/camera2/LensShadingMap.java
@@ -0,0 +1,243 @@
+/*
+ * 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.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+import static android.hardware.camera2.RggbChannelVector.*;
+
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+import java.util.Arrays;
+
+/**
+ * Immutable class for describing a {@code 4 x N x M} lens shading map of floats.
+ *
+ * @see CameraCharacteristics#LENS_SHADING_MAP
+ */
+public final class LensShadingMap {
+
+ /**
+ * The smallest gain factor in this map.
+ *
+ * <p>All values in this map will be at least this large.</p>
+ */
+ public static final float MINIMUM_GAIN_FACTOR = 1.0f;
+
+ /**
+ * Create a new immutable LensShadingMap instance.
+ *
+ * <p>The elements must be stored in a row-major order (fully packed).</p>
+ *
+ * <p>This constructor takes over the array; do not write to the array afterwards.</p>
+ *
+ * @param elements
+ * An array of elements whose length is
+ * {@code RggbChannelVector.COUNT * rows * columns}
+ *
+ * @throws IllegalArgumentException
+ * if the {@code elements} array length is invalid,
+ * if any of the subelems are not finite or less than {@value #MINIMUM_GAIN_FACTOR},
+ * or if rows or columns is not positive
+ * @throws NullPointerException
+ * if {@code elements} is {@code null}
+ *
+ * @hide
+ */
+ public LensShadingMap(final float[] elements, final int rows, final int columns) {
+
+ mRows = checkArgumentPositive(rows, "rows must be positive");
+ mColumns = checkArgumentPositive(rows, "columns must be positive");
+ mElements = checkNotNull(elements, "elements must not be null");
+
+ if (elements.length != getGainFactorCount()) {
+ throw new IllegalArgumentException("elements must be " + getGainFactorCount() +
+ " length");
+ }
+
+ // Every element must be finite and >= 1.0f
+ checkArrayElementsInRange(elements, MINIMUM_GAIN_FACTOR, Float.MAX_VALUE, "elements");
+ }
+
+ /**
+ * Get the number of rows in this map.
+ */
+ public int getRowCount() {
+ return mRows;
+ }
+
+ /**
+ * Get the number of columns in this map.
+ */
+ public int getColumnCount() {
+ return mColumns;
+ }
+
+ /**
+ * Get the total number of gain factors in this map.
+ *
+ * <p>A single gain factor contains exactly one color channel.
+ * Use with {@link #copyGainFactors} to allocate a large-enough array.</p>
+ */
+ public int getGainFactorCount() {
+ return mRows * mColumns * COUNT;
+ }
+
+ /**
+ * Get a single color channel gain factor from this lens shading map by its row and column.
+ *
+ * <p>The rows must be within the range [0, {@link #getRowCount}),
+ * the column must be within the range [0, {@link #getColumnCount}),
+ * and the color channel must be within the range [0, {@value RggbChannelVector#COUNT}).</p>
+ *
+ * <p>The channel order is {@code [R, Geven, Godd, B]}, where
+ * {@code Geven} is the green channel for the even rows of a Bayer pattern, and
+ * {@code Godd} is the odd rows.
+ * </p>
+ *
+ * @param colorChannel color channel from {@code [R, Geven, Godd, B]}
+ * @param column within the range [0, {@link #getColumnCount})
+ * @param row within the range [0, {@link #getRowCount})
+ *
+ * @return a gain factor >= {@value #MINIMUM_GAIN_FACTOR}
+ *
+ * @throws IllegalArgumentException if any of the parameters was out of range
+ *
+ * @see #RED
+ * @see #GREEN_EVEN
+ * @see #GREEN_ODD
+ * @see #BLUE
+ * @see #getRowCount
+ * @see #getColumnCount
+ */
+ public float getGainFactor(final int colorChannel, final int column, final int row) {
+ if (colorChannel < 0 || colorChannel > COUNT) {
+ throw new IllegalArgumentException("colorChannel out of range");
+ } else if (column < 0 || column >= mColumns) {
+ throw new IllegalArgumentException("column out of range");
+ } else if (row < 0 || row >= mRows) {
+ throw new IllegalArgumentException("row out of range");
+ }
+
+ return mElements[colorChannel + (row * mColumns + column) * COUNT ];
+ }
+
+ /**
+ * Get a gain factor vector from this lens shading map by its row and column.
+ *
+ * <p>The rows must be within the range [0, {@link #getRowCount}),
+ * the column must be within the range [0, {@link #getColumnCount}).</p>
+ *
+ * @param column within the range [0, {@link #getColumnCount})
+ * @param row within the range [0, {@link #getRowCount})
+ *
+ * @return an {@link RggbChannelVector} where each gain factor >= {@value #MINIMUM_GAIN_FACTOR}
+ *
+ * @throws IllegalArgumentException if any of the parameters was out of range
+ *
+ * @see #getRowCount
+ * @see #getColumnCount
+ */
+ public RggbChannelVector getGainFactorVector(final int column, final int row) {
+ if (column < 0 || column >= mColumns) {
+ throw new IllegalArgumentException("column out of range");
+ } else if (row < 0 || row >= mRows) {
+ throw new IllegalArgumentException("row out of range");
+ }
+
+ final int offset = (row * mColumns + column) * COUNT;
+
+ final float red =
+ mElements[RED + offset];
+ final float greenEven =
+ mElements[GREEN_EVEN + offset];
+ final float greenOdd =
+ mElements[GREEN_ODD + offset];
+ final float blue =
+ mElements[BLUE + offset];
+
+ return new RggbChannelVector(red, greenEven, greenOdd, blue);
+ }
+
+ /**
+ * Copy all gain factors in row-major order from this lens shading map into the destination.
+ *
+ * <p>Each gain factor will be >= {@link #MINIMUM_GAIN_FACTOR}.</p>
+ *
+ * @param destination
+ * an array big enough to hold at least {@link RggbChannelVector#COUNT}
+ * elements after the {@code offset}
+ * @param offset
+ * a non-negative offset into the array
+ * @throws NullPointerException
+ * If {@code destination} was {@code null}
+ * @throws IllegalArgumentException
+ * If offset was negative
+ * @throws ArrayIndexOutOfBoundsException
+ * If there's not enough room to write the elements at the specified destination and
+ * offset.
+ *
+ * @see CaptureResult#STATISTICS_LENS_SHADING_MAP
+ */
+ public void copyGainFactors(final float[] destination, final int offset) {
+ checkArgumentNonnegative(offset, "offset must not be negative");
+ checkNotNull(destination, "destination must not be null");
+ if (destination.length + offset < getGainFactorCount()) {
+ throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
+ }
+
+ System.arraycopy(mElements, /*srcPos*/0, destination, offset, getGainFactorCount());
+ }
+
+ /**
+ * Check if this LensShadingMap is equal to another LensShadingMap.
+ *
+ * <p>Two lens shading maps are equal if and only if they have the same rows/columns,
+ * and all of their elements are {@link Object#equals equal}.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof LensShadingMap) {
+ final LensShadingMap other = (LensShadingMap) obj;
+ return mRows == other.mRows
+ && mColumns == other.mColumns
+ && Arrays.equals(mElements, other.mElements);
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ int elemsHash = HashCodeHelpers.hashCode(mElements);
+ return HashCodeHelpers.hashCode(mRows, mColumns, elemsHash);
+ }
+
+
+ private final int mRows;
+ private final int mColumns;
+ private final float[] mElements;
+};
diff --git a/core/java/android/hardware/camera2/MeteringRectangle.java b/core/java/android/hardware/camera2/MeteringRectangle.java
new file mode 100644
index 0000000..ff7a745
--- /dev/null
+++ b/core/java/android/hardware/camera2/MeteringRectangle.java
@@ -0,0 +1,224 @@
+/*
+ * 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.hardware.camera2;
+
+import android.util.Size;
+import static com.android.internal.util.Preconditions.*;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+/**
+ * An immutable class to represent a rectangle {@code (x,y, width, height)} with an
+ * additional weight component.
+ *
+ * </p>The rectangle is defined to be inclusive of the specified coordinates.</p>
+ *
+ * <p>When used with a {@link CaptureRequest}, the coordinate system is based on the active pixel
+ * array, with {@code (0,0)} being the top-left pixel in the
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE active pixel array}, and
+ * {@code (android.sensor.info.activeArraySize.width - 1,
+ * android.sensor.info.activeArraySize.height - 1)}
+ * being the bottom-right pixel in the active pixel array.
+ * </p>
+ *
+ * <p>The metering weight is nonnegative.</p>
+ */
+public final class MeteringRectangle {
+
+ private final int mX;
+ private final int mY;
+ private final int mWidth;
+ private final int mHeight;
+ private final int mWeight;
+
+ /**
+ * Create a new metering rectangle.
+ *
+ * @param x coordinate >= 0
+ * @param y coordinate >= 0
+ * @param width width >= 0
+ * @param height height >= 0
+ * @param meteringWeight weight >= 0
+ *
+ * @throws IllegalArgumentException if any of the parameters were non-negative
+ */
+ public MeteringRectangle(int x, int y, int width, int height, int meteringWeight) {
+ mX = checkArgumentNonnegative(x, "x must be nonnegative");
+ mY = checkArgumentNonnegative(y, "y must be nonnegative");
+ mWidth = checkArgumentNonnegative(width, "width must be nonnegative");
+ mHeight = checkArgumentNonnegative(height, "height must be nonnegative");
+ mWeight = checkArgumentNonnegative(meteringWeight, "meteringWeight must be nonnegative");
+ }
+
+ /**
+ * Create a new metering rectangle.
+ *
+ * @param xy a non-{@code null} {@link Point} with both x,y >= 0
+ * @param dimensions a non-{@code null} {@link android.util.Size Size} with width, height >= 0
+ * @param meteringWeight weight >= 0
+ *
+ * @throws IllegalArgumentException if any of the parameters were non-negative
+ * @throws NullPointerException if any of the arguments were null
+ */
+ public MeteringRectangle(Point xy, Size dimensions, int meteringWeight) {
+ checkNotNull(xy, "xy must not be null");
+ checkNotNull(dimensions, "dimensions must not be null");
+
+ mX = checkArgumentNonnegative(xy.x, "x must be nonnegative");
+ mY = checkArgumentNonnegative(xy.y, "y must be nonnegative");
+ mWidth = checkArgumentNonnegative(dimensions.getWidth(), "width must be nonnegative");
+ mHeight = checkArgumentNonnegative(dimensions.getHeight(), "height must be nonnegative");
+ mWeight = checkArgumentNonnegative(meteringWeight, "meteringWeight must be nonnegative");
+ }
+
+ /**
+ * Create a new metering rectangle.
+ *
+ * @param rect a non-{@code null} rectangle with all x,y,w,h dimensions >= 0
+ * @param meteringWeight weight >= 0
+ *
+ * @throws IllegalArgumentException if any of the parameters were non-negative
+ * @throws NullPointerException if any of the arguments were null
+ */
+ public MeteringRectangle(Rect rect, int meteringWeight) {
+ checkNotNull(rect, "rect must not be null");
+
+ mX = checkArgumentNonnegative(rect.left, "rect.left must be nonnegative");
+ mY = checkArgumentNonnegative(rect.top, "rect.top must be nonnegative");
+ mWidth = checkArgumentNonnegative(rect.width(), "rect.width must be nonnegative");
+ mHeight = checkArgumentNonnegative(rect.height(), "rect.height must be nonnegative");
+ mWeight = checkArgumentNonnegative(meteringWeight, "meteringWeight must be nonnegative");
+ }
+
+ /**
+ * Return the X coordinate of the left side of the rectangle.
+ *
+ * @return x coordinate >= 0
+ */
+ public int getX() {
+ return mX;
+ }
+
+ /**
+ * Return the Y coordinate of the upper side of the rectangle.
+ *
+ * @return y coordinate >= 0
+ */
+ public int getY() {
+ return mY;
+ }
+
+ /**
+ * Return the width of the rectangle.
+ *
+ * @return width >= 0
+ */
+ public int getWidth() {
+ return mWidth;
+ }
+
+ /**
+ * Return the height of the rectangle.
+ *
+ * @return height >= 0
+ */
+ public int getHeight() {
+ return mHeight;
+ }
+
+ /**
+ * Return the metering weight of the rectangle.
+ *
+ * @return weight >= 0
+ */
+ public int getMeteringWeight() {
+ return mWeight;
+ }
+
+ /**
+ * Convenience method to create the upper-left (X,Y) coordinate as a {@link Point}.
+ *
+ * @return {@code (x,y)} point with both x,y >= 0
+ */
+ public Point getUpperLeftPoint() {
+ return new Point(mX, mY);
+ }
+
+ /**
+ * Convenience method to create the size from this metering rectangle.
+ *
+ * <p>This strips away the X,Y,weight from the rectangle.</p>
+ *
+ * @return a Size with non-negative width and height
+ */
+ public Size getSize() {
+ return new Size(mWidth, mHeight);
+ }
+
+ /**
+ * Convenience method to create a {@link Rect} from this metering rectangle.
+ *
+ * <p>This strips away the weight from the rectangle.</p>
+ *
+ * @return a {@link Rect} with non-negative x1, y1, x2, y2
+ */
+ public Rect getRect() {
+ return new Rect(mX, mY, mX + mWidth, mY + mHeight);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(final Object other) {
+ if (other instanceof MeteringRectangle) {
+ return equals(other);
+ }
+ return false;
+ }
+
+ /**
+ * Compare two metering rectangles to see if they are equal.
+ *
+ * Two weighted rectangles are only considered equal if each of their components
+ * (x, y, width, height, weight) is respectively equal.
+ *
+ * @param other Another MeteringRectangle
+ *
+ * @return {@code true} if the metering rectangles are equal, {@code false} otherwise
+ */
+ public boolean equals(final MeteringRectangle other) {
+ if (other == null) {
+ return false;
+ }
+
+ return (mX == other.mX
+ && mY == other.mY
+ && mWidth == other.mWidth
+ && mHeight == other.mHeight
+ && mWidth == other.mWidth);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return HashCodeHelpers.hashCode(mX, mY, mWidth, mHeight, mWeight);
+ }
+}
diff --git a/core/java/android/hardware/camera2/ReprocessFormatsMap.java b/core/java/android/hardware/camera2/ReprocessFormatsMap.java
new file mode 100644
index 0000000..c6c59d4
--- /dev/null
+++ b/core/java/android/hardware/camera2/ReprocessFormatsMap.java
@@ -0,0 +1,258 @@
+/*
+ * 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.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+import java.util.Arrays;
+
+/**
+ * Immutable class to store the input to output formats
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP map} to be used for with
+ * camera image reprocessing.
+ *
+ * <p>
+ * The mapping of image formats that are supported by this camera device for input streams,
+ * to their corresponding output formats.</p>
+ *
+ * <p>
+ * Attempting to configure an input stream with output streams not listed as available in this map
+ * is not valid.
+ * </p>
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
+ *
+ * <!-- hide this until we expose input streams through public API -->
+ * @hide
+ */
+public final class ReprocessFormatsMap {
+ /**
+ * Create a new {@link ReprocessFormatsMap}
+ *
+ * <p>This value is encoded as a variable-size array-of-arrays.
+ * The inner array always contains {@code [format, length, ...]} where ... has length elements.
+ * An inner array is followed by another inner array if the total metadata entry size hasn't
+ * yet been exceeded.</p>
+ *
+ * <p>Entry must not be {@code null}. Empty array is acceptable.</p>
+ *
+ * <p>The entry array ownership is passed to this instance after construction; do not
+ * write to it afterwards.</p>
+ *
+ * @param entry Array of ints, not yet deserialized (not-null)
+ *
+ * @throws IllegalArgumentException
+ * if the data was poorly formatted
+ * (missing output format length or too few output formats)
+ * @throws NullPointerException
+ * if entry was null
+ *
+ * @hide
+ */
+ public ReprocessFormatsMap(final int[] entry) {
+ checkNotNull(entry, "entry must not be null");
+
+ int numInputs = 0;
+ int left = entry.length;
+ for (int i = 0; i < entry.length; ) {
+ final int format = entry[i];
+
+ left--;
+ i++;
+
+ if (left < 1) {
+ throw new IllegalArgumentException(
+ String.format("Input %x had no output format length listed", format));
+ }
+
+ final int length = entry[i];
+ left--;
+ i++;
+
+ if (length > 0) {
+ if (left < length) {
+ throw new IllegalArgumentException(
+ String.format(
+ "Input %x had too few output formats listed (actual: %d, " +
+ "expected: %d)", format, left, length));
+ }
+
+ i += length;
+ left -= length;
+ }
+
+ numInputs++;
+ }
+
+ mEntry = entry;
+ mInputCount = numInputs;
+ }
+
+ /**
+ * Get a list of all input image formats that can be used to reprocess an input
+ * stream into an output stream.
+ *
+ * <p>Use this input format to look up the available output formats with {@link #getOutputs}.
+ * </p>
+ *
+ * @return an array of inputs (possibly empty, but never {@code null})
+ *
+ * @see ImageFormat
+ * @see #getOutputs
+ */
+ public int[] getInputs() {
+ final int[] inputs = new int[mInputCount];
+
+ int left = mEntry.length;
+ for (int i = 0, j = 0; i < mEntry.length; j++) {
+ final int format = mEntry[i];
+
+ left--;
+ i++;
+
+ if (left < 1) {
+ throw new AssertionError(
+ String.format("Input %x had no output format length listed", format));
+ }
+ // TODO: check format is a valid input format
+
+ final int length = mEntry[i];
+ left--;
+ i++;
+
+ if (length > 0) {
+ if (left < length) {
+ throw new AssertionError(
+ String.format(
+ "Input %x had too few output formats listed (actual: %d, " +
+ "expected: %d)", format, left, length));
+ }
+
+ i += length;
+ left -= length;
+ }
+
+ // TODO: check output format is a valid output format
+
+ inputs[j] = format;
+ }
+
+ return inputs;
+ }
+
+ /**
+ * Get the list of output formats that can be reprocessed into from the input {@code format}.
+ *
+ * <p>The input {@code format} must be one of the formats returned by {@link #getInputs}.</p>
+ *
+ * @param format an input format
+ *
+ * @return list of output image formats
+ *
+ * @see ImageFormat
+ * @see #getInputs
+ */
+ public int[] getOutputs(final int format) {
+
+ int left = mEntry.length;
+ for (int i = 0; i < mEntry.length; ) {
+ final int inputFormat = mEntry[i];
+
+ left--;
+ i++;
+
+ if (left < 1) {
+ throw new AssertionError(
+ String.format("Input %x had no output format length listed", format));
+ }
+
+ final int length = mEntry[i];
+ left--;
+ i++;
+
+ if (length > 0) {
+ if (left < length) {
+ throw new AssertionError(
+ String.format(
+ "Input %x had too few output formats listed (actual: %d, " +
+ "expected: %d)", format, left, length));
+ }
+ }
+
+ if (inputFormat == format) {
+ int[] outputs = new int[length];
+
+ // Copying manually faster than System.arraycopy for small arrays
+ for (int k = 0; k < length; ++k) {
+ outputs[k] = mEntry[i + k];
+ }
+
+ return outputs;
+ }
+
+ i += length;
+ left -= length;
+
+ }
+
+ throw new IllegalArgumentException(
+ String.format("Input format %x was not one in #getInputs", format));
+ }
+
+ /**
+ * Check if this {@link ReprocessFormatsMap} is equal to another
+ * {@link ReprocessFormatsMap}.
+ *
+ * <p>These two objects are only equal if and only if each of the respective elements is equal.
+ * </p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ReprocessFormatsMap) {
+ final ReprocessFormatsMap other = (ReprocessFormatsMap) obj;
+ // Do not compare anything besides mEntry, since the rest of the values are derived
+ return Arrays.equals(mEntry, other.mEntry);
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ // Do not hash anything besides mEntry since the rest of the values are derived
+ return HashCodeHelpers.hashCode(mEntry);
+ }
+
+ private final int[] mEntry;
+ /*
+ * Dependent fields: values are derived from mEntry
+ */
+ private final int mInputCount;
+}
diff --git a/core/java/android/hardware/camera2/RggbChannelVector.java b/core/java/android/hardware/camera2/RggbChannelVector.java
new file mode 100644
index 0000000..80167c6
--- /dev/null
+++ b/core/java/android/hardware/camera2/RggbChannelVector.java
@@ -0,0 +1,199 @@
+/*
+ * 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.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Immutable class to store a 4-element vector of floats indexable by a bayer RAW 2x2 pixel block.
+ */
+public final class RggbChannelVector {
+ /**
+ * The number of color channels in this vector.
+ */
+ public static final int COUNT = 4;
+
+ /** Red color channel in a bayer Raw pattern. */
+ public static final int RED = 0;
+
+ /** Green color channel in a bayer Raw pattern used by the even rows. */
+ public static final int GREEN_EVEN = 1;
+
+ /** Green color channel in a bayer Raw pattern used by the odd rows. */
+ public static final int GREEN_ODD = 2;
+
+ /** Blue color channel in a bayer Raw pattern. */
+ public static final int BLUE = 3;
+
+ /**
+ * Create a new {@link RggbChannelVector} from an RGGB 2x2 pixel.
+ *
+ * <p>All pixel values are considered normalized within {@code [0.0f, 1.0f]}
+ * (i.e. {@code 1.0f} could be linearized to {@code 255} if converting to a
+ * non-floating point pixel representation).</p>
+ *
+ * <p>All arguments must be finite; NaN and infinity is not allowed.</p>
+ *
+ * @param red red pixel
+ * @param greenEven green pixel (even row)
+ * @param greenOdd green pixel (odd row)
+ * @param blue blue pixel
+ *
+ * @throws IllegalArgumentException if any of the arguments were not finite
+ */
+ public RggbChannelVector(final float red, final float greenEven, final float greenOdd,
+ final float blue) {
+ mRed = checkArgumentFinite(red, "red");
+ mGreenEven = checkArgumentFinite(greenEven, "greenEven");
+ mGreenOdd = checkArgumentFinite(greenOdd, "greenOdd");
+ mBlue = checkArgumentFinite(blue, "blue");
+ }
+
+ /**
+ * Get the red component.
+ *
+ * @return a floating point value (guaranteed to be finite)
+ */
+ public final float getRed() {
+ return mRed;
+ }
+
+ /**
+ * Get the green (even rows) component.
+ *
+ * @return a floating point value (guaranteed to be finite)
+ */
+ public float getGreenEven() {
+ return mGreenEven;
+ }
+
+ /**
+ * Get the green (odd rows) component.
+ *
+ * @return a floating point value (guaranteed to be finite)
+ */
+ public float getGreenOdd() {
+ return mGreenOdd;
+ }
+
+ /**
+ * Get the blue component.
+ *
+ * @return a floating point value (guaranteed to be finite)
+ */
+ public float getBlue() {
+ return mBlue;
+ }
+
+ /**
+ * Get the component by the color channel index.
+ *
+ * <p>{@code colorChannel} must be one of {@link #RED}, {@link #GREEN_EVEN}, {@link #GREEN_ODD},
+ * {@link #BLUE}.</p>
+ *
+ * @param colorChannel greater or equal to {@code 0} and less than {@link #COUNT}
+ * @return a floating point value (guaranteed to be finite)
+ *
+ * @throws IllegalArgumentException if {@code colorChannel} was out of range
+ */
+ public float getComponent(final int colorChannel) {
+ if (colorChannel < 0 || colorChannel >= COUNT) {
+ throw new IllegalArgumentException("Color channel out of range");
+ }
+
+ switch (colorChannel) {
+ case RED:
+ return mRed;
+ case GREEN_EVEN:
+ return mGreenEven;
+ case GREEN_ODD:
+ return mGreenOdd;
+ case BLUE:
+ return mBlue;
+ default:
+ throw new AssertionError("Unhandled case " + colorChannel);
+ }
+ }
+
+ /**
+ * Copy the vector into the destination in the order {@code [R, Geven, Godd, B]}.
+ *
+ * @param destination
+ * an array big enough to hold at least {@value #COUNT} elements after the
+ * {@code offset}
+ * @param offset
+ * a non-negative offset into the array
+ *
+ * @throws NullPointerException
+ * If {@code destination} was {@code null}
+ * @throws ArrayIndexOutOfBoundsException
+ * If there's not enough room to write the elements at the specified destination and
+ * offset.
+ */
+ public void copyTo(final float[] destination, final int offset) {
+ checkNotNull(destination, "destination must not be null");
+ if (destination.length + offset < COUNT) {
+ throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
+ }
+
+ destination[offset + RED] = mRed;
+ destination[offset + GREEN_EVEN] = mGreenEven;
+ destination[offset + GREEN_ODD] = mGreenOdd;
+ destination[offset + BLUE] = mBlue;
+ }
+
+ /**
+ * Check if this {@link RggbChannelVector} is equal to another {@link RggbChannelVector}.
+ *
+ * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof RggbChannelVector) {
+ final RggbChannelVector other = (RggbChannelVector) obj;
+ return mRed == other.mRed &&
+ mGreenEven == other.mGreenEven &&
+ mGreenOdd == other.mGreenOdd &&
+ mBlue == other.mBlue;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return Float.floatToIntBits(mRed) ^
+ Float.floatToIntBits(mGreenEven) ^
+ Float.floatToIntBits(mGreenOdd) ^
+ Float.floatToIntBits(mBlue);
+ }
+
+ private final float mRed;
+ private final float mGreenEven;
+ private final float mGreenOdd;
+ private final float mBlue;
+}
diff --git a/core/java/android/hardware/camera2/Size.java b/core/java/android/hardware/camera2/Size.java
index 45aaeae..9328a003 100644
--- a/core/java/android/hardware/camera2/Size.java
+++ b/core/java/android/hardware/camera2/Size.java
@@ -16,32 +16,55 @@
package android.hardware.camera2;
+// TODO: Delete this class, since it was moved to android.util as public API
+
/**
- * A simple immutable class for describing the dimensions of camera image
- * buffers.
+ * Immutable class for describing width and height dimensions in pixels.
+ *
+ * @hide
*/
public final class Size {
/**
- * Create a new immutable Size instance
+ * Create a new immutable Size instance.
*
- * @param width The width to store in the Size instance
- * @param height The height to store in the Size instance
+ * @param width The width of the size, in pixels
+ * @param height The height of the size, in pixels
*/
- public Size(int width, int height) {
+ public Size(final int width, final int height) {
mWidth = width;
mHeight = height;
}
+ /**
+ * Get the width of the size (in pixels).
+ * @return width
+ */
public final int getWidth() {
return mWidth;
}
+ /**
+ * Get the height of the size (in pixels).
+ * @return height
+ */
public final int getHeight() {
return mHeight;
}
+ /**
+ * Check if this size is equal to another size.
+ * <p>
+ * Two sizes are equal if and only if both their widths and heights are
+ * equal.
+ * </p>
+ * <p>
+ * A size object is never equal to any other type of object.
+ * </p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
@@ -49,27 +72,29 @@
return true;
}
if (obj instanceof Size) {
- Size other = (Size) obj;
+ final Size other = (Size) obj;
return mWidth == other.mWidth && mHeight == other.mHeight;
}
return false;
}
+ /**
+ * Return the size represented as a string with the format {@code "WxH"}
+ *
+ * @return string representation of the size
+ */
@Override
public String toString() {
return mWidth + "x" + mHeight;
}
+ /**
+ * {@inheritDoc}
+ */
@Override
public int hashCode() {
- final long INT_MASK = 0xffffffffL;
-
- long asLong = INT_MASK & mWidth;
- asLong <<= 32;
-
- asLong |= (INT_MASK & mHeight);
-
- return ((Long)asLong).hashCode();
+ // assuming most sizes are <2^16, doing a rotate will give us perfect hashing
+ return mHeight ^ ((mWidth << (Integer.SIZE / 2)) | (mWidth >>> (Integer.SIZE / 2)));
}
private final int mWidth;
diff --git a/core/java/android/hardware/camera2/StreamConfiguration.java b/core/java/android/hardware/camera2/StreamConfiguration.java
new file mode 100644
index 0000000..c53dd7c
--- /dev/null
+++ b/core/java/android/hardware/camera2/StreamConfiguration.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 android.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+import static android.hardware.camera2.StreamConfigurationMap.checkArgumentFormatInternal;
+
+import android.graphics.ImageFormat;
+import android.hardware.camera2.impl.HashCodeHelpers;
+import android.util.Size;
+
+/**
+ * Immutable class to store the available stream
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS configurations} to be used
+ * when configuring streams with {@link CameraDevice#configureOutputs}.
+ * <!-- TODO: link to input stream configuration -->
+ *
+ * <p>This is the authoritative list for all input/output formats (and sizes respectively
+ * for that format) that are supported by a camera device.</p>
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
+ *
+ * @hide
+ */
+public final class StreamConfiguration {
+
+ /**
+ * Create a new {@link StreamConfiguration}.
+ *
+ * @param format image format
+ * @param width image width, in pixels (positive)
+ * @param height image height, in pixels (positive)
+ * @param input true if this is an input configuration, false for output configurations
+ *
+ * @throws IllegalArgumentException
+ * if width/height were not positive
+ * or if the format was not user-defined in ImageFormat/PixelFormat
+ * (IMPL_DEFINED is ok)
+ *
+ * @hide
+ */
+ public StreamConfiguration(
+ final int format, final int width, final int height, final boolean input) {
+ mFormat = checkArgumentFormatInternal(format);
+ mWidth = checkArgumentPositive(width, "width must be positive");
+ mHeight = checkArgumentPositive(width, "height must be positive");
+ mInput = input;
+ }
+
+ /**
+ * Get the image {@code format} in this stream configuration.
+ *
+ * @return an integer format
+ *
+ * @see ImageFormat
+ */
+ public final int getFormat() {
+ return mFormat;
+ }
+
+
+ /**
+ * Return the width of the stream configuration.
+ *
+ * @return width > 0
+ */
+ public int getWidth() {
+ return mWidth;
+ }
+
+ /**
+ * Return the height of the stream configuration.
+ *
+ * @return height > 0
+ */
+ public int getHeight() {
+ return mHeight;
+ }
+
+ /**
+ * Convenience method to return the size of this stream configuration.
+ *
+ * @return a Size with positive width and height
+ */
+ public Size getSize() {
+ return new Size(mWidth, mHeight);
+ }
+
+ /**
+ * Determines if this configuration is usable for input streams.
+ *
+ * <p>Input and output stream configurations are not interchangeable;
+ * input stream configurations must be used when configuring inputs.</p>
+ *
+ * @return {@code true} if input configuration, {@code false} otherwise
+ */
+ public boolean isInput() {
+ return mInput;
+ }
+
+ /**
+ * Determines if this configuration is usable for output streams.
+ *
+ * <p>Input and output stream configurations are not interchangeable;
+ * out stream configurations must be used when configuring outputs.</p>
+ *
+ * @return {@code true} if output configuration, {@code false} otherwise
+ *
+ * @see CameraDevice#configureOutputs
+ */
+ public boolean isOutput() {
+ return !mInput;
+ }
+
+ /**
+ * Check if this {@link StreamConfiguration} is equal to another {@link StreamConfiguration}.
+ *
+ * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof StreamConfiguration) {
+ final StreamConfiguration other = (StreamConfiguration) obj;
+ return mFormat == other.mFormat &&
+ mWidth == other.mWidth &&
+ mHeight == other.mHeight &&
+ mInput == other.mInput;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return HashCodeHelpers.hashCode(mFormat, mWidth, mHeight, mInput ? 1 : 0);
+ }
+
+ private final int mFormat;
+ private final int mWidth;
+ private final int mHeight;
+ private final boolean mInput;
+}
diff --git a/core/java/android/hardware/camera2/StreamConfigurationDuration.java b/core/java/android/hardware/camera2/StreamConfigurationDuration.java
new file mode 100644
index 0000000..189ae62
--- /dev/null
+++ b/core/java/android/hardware/camera2/StreamConfigurationDuration.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.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+import static android.hardware.camera2.StreamConfigurationMap.checkArgumentFormatInternal;
+
+import android.graphics.ImageFormat;
+import android.hardware.camera2.impl.HashCodeHelpers;
+import android.util.Size;
+
+/**
+ * Immutable class to store a time duration for any given format/size combination.
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
+ * @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS
+ *
+ * @hide
+ */
+public final class StreamConfigurationDuration {
+
+ /**
+ * Create a new {@link StreamConfigurationDuration}.
+ *
+ * @param format image format
+ * @param width image width, in pixels (positive)
+ * @param height image height, in pixels (positive)
+ * @param durationNs duration in nanoseconds (non-negative)
+ *
+ * @throws IllegalArgumentException
+ * if width/height were not positive, or durationNs was negative
+ * or if the format was not user-defined in ImageFormat/PixelFormat
+ * (IMPL_DEFINED is OK)
+ *
+ *
+ * @hide
+ */
+ public StreamConfigurationDuration(
+ final int format, final int width, final int height, final long durationNs) {
+ mFormat = checkArgumentFormatInternal(format);
+ mWidth = checkArgumentPositive(width, "width must be positive");
+ mHeight = checkArgumentPositive(width, "height must be positive");
+ mDurationNs = checkArgumentNonnegative(durationNs, "durationNs must be non-negative");
+ }
+
+ /**
+ * Get the image {@code format} in this stream configuration duration
+ *
+ * @return an integer format
+ *
+ * @see ImageFormat
+ */
+ public final int getFormat() {
+ return mFormat;
+ }
+
+
+ /**
+ * Return the width of the stream configuration duration.
+ *
+ * @return width > 0
+ */
+ public int getWidth() {
+ return mWidth;
+ }
+
+ /**
+ * Return the height of the stream configuration duration
+ *
+ * @return height > 0
+ */
+ public int getHeight() {
+ return mHeight;
+ }
+
+ /**
+ * Convenience method to return the size of this stream configuration duration.
+ *
+ * @return a Size with positive width and height
+ */
+ public Size getSize() {
+ return new Size(mWidth, mHeight);
+ }
+
+ /**
+ * Get the time duration (in nanoseconds).
+ *
+ * @return long >= 0
+ */
+ public long getDuration() {
+ return mDurationNs;
+ }
+
+ /**
+ * Check if this {@link StreamConfigurationDuration} is equal to another
+ * {@link StreamConfigurationDuration}.
+ *
+ * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof StreamConfigurationDuration) {
+ final StreamConfigurationDuration other = (StreamConfigurationDuration) obj;
+ return mFormat == other.mFormat &&
+ mWidth == other.mWidth &&
+ mHeight == other.mHeight &&
+ mDurationNs == other.mDurationNs;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return HashCodeHelpers.hashCode(mFormat, mWidth, mHeight,
+ (int) mDurationNs, (int)(mDurationNs >>> Integer.SIZE));
+ }
+
+ private final int mFormat;
+ private final int mWidth;
+ private final int mHeight;
+ private final long mDurationNs;
+}
diff --git a/core/java/android/hardware/camera2/StreamConfigurationMap.java b/core/java/android/hardware/camera2/StreamConfigurationMap.java
new file mode 100644
index 0000000..e24fd1b
--- /dev/null
+++ b/core/java/android/hardware/camera2/StreamConfigurationMap.java
@@ -0,0 +1,508 @@
+/*
+ * 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.hardware.camera2;
+
+import android.graphics.ImageFormat;
+import android.graphics.PixelFormat;
+import android.hardware.camera2.impl.HashCodeHelpers;
+import android.view.Surface;
+import android.util.Size;
+
+import java.util.Arrays;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Immutable class to store the available stream
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS configurations} to be used
+ * when configuring streams with {@link CameraDevice#configureOutputs}.
+ * <!-- TODO: link to input stream configuration -->
+ *
+ * <p>This is the authoritative list for all <!-- input/ -->output formats (and sizes respectively
+ * for that format) that are supported by a camera device.</p>
+ *
+ * <p>This also contains the minimum frame durations and stall durations for each format/size
+ * combination that can be used to calculate effective frame rate when submitting multiple captures.
+ * </p>
+ *
+ * <p>An instance of this object is available from {@link CameraCharacteristics} using
+ * the {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS} key and the
+ * {@link CameraCharacteristics#get} method.</p.
+ *
+ * <pre>{@code
+ * CameraCharacteristics characteristics = ...;
+ * StreamConfigurationMap configs = characteristics.get(
+ * CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+ * }</pre>
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
+ * @see CameraDevice#configureOutputs
+ */
+public final class StreamConfigurationMap {
+
+ /**
+ * Create a new {@link StreamConfigurationMap}.
+ *
+ * <p>The array parameters ownership is passed to this object after creation; do not
+ * write to them after this constructor is invoked.</p>
+ *
+ * @param configurations a non-{@code null} array of {@link StreamConfiguration}
+ * @param durations a non-{@code null} array of {@link StreamConfigurationDuration}
+ *
+ * @throws NullPointerException if any of the arguments or subelements were {@code null}
+ *
+ * @hide
+ */
+ public StreamConfigurationMap(
+ StreamConfiguration[] configurations,
+ StreamConfigurationDuration[] durations) {
+ // TODO: format check against ImageFormat/PixelFormat ?
+
+ mConfigurations = checkArrayElementsNotNull(configurations, "configurations");
+ mDurations = checkArrayElementsNotNull(durations, "durations");
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get the image {@code format} output formats in this stream configuration.
+ *
+ * <p>All image formats returned by this function will be defined in either {@link ImageFormat}
+ * or in {@link PixelFormat} (and there is no possibility of collision).</p>
+ *
+ * <p>Formats listed in this array are guaranteed to return true if queried with
+ * {@link #isOutputSupportedFor(int).</p>
+ *
+ * @return an array of integer format
+ *
+ * @see ImageFormat
+ * @see PixelFormat
+ */
+ public final int[] getOutputFormats() {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get the image {@code format} input formats in this stream configuration.
+ *
+ * <p>All image formats returned by this function will be defined in either {@link ImageFormat}
+ * or in {@link PixelFormat} (and there is no possibility of collision).</p>
+ *
+ * @return an array of integer format
+ *
+ * @see ImageFormat
+ * @see PixelFormat
+ *
+ * @hide
+ */
+ public final int[] getInputFormats() {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get the supported input sizes for this input format.
+ *
+ * <p>The format must have come from {@link #getInputFormats}; otherwise
+ * {@code null} is returned.</p>
+ *
+ * @param format a format from {@link #getInputFormats}
+ * @return a non-empty array of sizes, or {@code null} if the format was not available.
+ *
+ * @hide
+ */
+ public Size[] getInputSizes(final int format) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Determine whether or not output streams can be
+ * {@link CameraDevice#configureOutputs configured} with a particular user-defined format.
+ *
+ * <p>This method determines that the output {@code format} is supported by the camera device;
+ * each output {@code surface} target may or may not itself support that {@code format}.
+ * Refer to the class which provides the surface for additional documentation.</p>
+ *
+ * <p>Formats for which this returns {@code true} are guaranteed to exist in the result
+ * returned by {@link #getOutputSizes}.</p>
+ *
+ * @param format an image format from either {@link ImageFormat} or {@link PixelFormat}
+ * @return
+ * {@code true} iff using a {@code surface} with this {@code format} will be
+ * supported with {@link CameraDevice#configureOutputs}
+ *
+ * @throws IllegalArgumentException
+ * if the image format was not a defined named constant
+ * from either {@link ImageFormat} or {@link PixelFormat}
+ *
+ * @see ImageFormat
+ * @see PixelFormat
+ * @see CameraDevice#configureOutputs
+ */
+ public boolean isOutputSupportedFor(int format) {
+ checkArgumentFormat(format);
+
+ final int[] formats = getOutputFormats();
+ for (int i = 0; i < formats.length; ++i) {
+ if (format == formats[i]) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Determine whether or not output streams can be configured with a particular class
+ * as a consumer.
+ *
+ * <p>The following list is generally usable for outputs:
+ * <ul>
+ * <li>{@link android.media.ImageReader} -
+ * Recommended for image processing or streaming to external resources (such as a file or
+ * network)
+ * <li>{@link android.media.MediaRecorder} -
+ * Recommended for recording video (simple to use)
+ * <li>{@link android.media.MediaCodec} -
+ * Recommended for recording video (more complicated to use, with more flexibility)
+ * <li>{@link android.renderscript.Allocation} -
+ * Recommended for image processing with {@link android.renderscript RenderScript}
+ * <li>{@link android.view.SurfaceHolder} -
+ * Recommended for low-power camera preview with {@link android.view.SurfaceView}
+ * <li>{@link android.graphics.SurfaceTexture} -
+ * Recommended for OpenGL-accelerated preview processing or compositing with
+ * {@link android.view.TextureView}
+ * </ul>
+ * </p>
+ *
+ * <p>Generally speaking this means that creating a {@link Surface} from that class <i>may</i>
+ * provide a producer endpoint that is suitable to be used with
+ * {@link CameraDevice#configureOutputs}.</p>
+ *
+ * <p>Since not all of the above classes support output of all format and size combinations,
+ * the particular combination should be queried with {@link #isOutputSupportedFor(Surface)}.</p>
+ *
+ * @param klass a non-{@code null} {@link Class} object reference
+ * @return {@code true} if this class is supported as an output, {@code false} otherwise
+ *
+ * @throws NullPointerException if {@code klass} was {@code null}
+ *
+ * @see CameraDevice#configureOutputs
+ * @see #isOutputSupportedFor(Surface)
+ */
+ public static <T> boolean isOutputSupportedFor(final Class<T> klass) {
+ checkNotNull(klass, "klass must not be null");
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Determine whether or not the {@code surface} in its current state is suitable to be
+ * {@link CameraDevice#configureOutputs configured} as an output.
+ *
+ * <p>Not all surfaces are usable with the {@link CameraDevice}, and not all configurations
+ * of that {@code surface} are compatible. Some classes that provide the {@code surface} are
+ * compatible with the {@link CameraDevice} in general
+ * (see {@link #isOutputSupportedFor(Class)}, but it is the caller's responsibility to put the
+ * {@code surface} into a state that will be compatible with the {@link CameraDevice}.</p>
+ *
+ * <p>Reasons for a {@code surface} being specifically incompatible might be:
+ * <ul>
+ * <li>Using a format that's not listed by {@link #getOutputFormats}
+ * <li>Using a format/size combination that's not listed by {@link #getOutputSizes}
+ * <li>The {@code surface} itself is not in a state where it can service a new producer.</p>
+ * </li>
+ * </ul>
+ *
+ * This is not an exhaustive list; see the particular class's documentation for further
+ * possible reasons of incompatibility.</p>
+ *
+ * @param surface a non-{@code null} {@link Surface} object reference
+ * @return {@code true} if this is supported, {@code false} otherwise
+ *
+ * @throws NullPointerException if {@code surface} was {@code null}
+ *
+ * @see CameraDevice#configureOutputs
+ * @see #isOutputSupportedFor(Class)
+ */
+ public boolean isOutputSupportedFor(final Surface surface) {
+ checkNotNull(surface, "surface must not be null");
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get a list of sizes compatible with {@code klass} to use as an output.
+ *
+ * <p>Since some of the supported classes may support additional formats beyond
+ * an opaque/implementation-defined (under-the-hood) format; this function only returns
+ * sizes for the implementation-defined format.</p>
+ *
+ * <p>Some classes such as {@link android.media.ImageReader} may only support user-defined
+ * formats; in particular {@link #isOutputSupportedFor(Class)} will return {@code true} for
+ * that class and this method will return an empty array (but not {@code null}).</p>
+ *
+ * <p>If a well-defined format such as {@code NV21} is required, use
+ * {@link #getOutputSizes(int)} instead.</p>
+ *
+ * <p>The {@code klass} should be a supported output, that querying
+ * {@code #isOutputSupportedFor(Class)} should return {@code true}.</p>
+ *
+ * @param klass
+ * a non-{@code null} {@link Class} object reference
+ * @return
+ * an array of supported sizes for implementation-defined formats,
+ * or {@code null} iff the {@code klass} is not a supported output
+ *
+ * @throws NullPointerException if {@code klass} was {@code null}
+ *
+ * @see #isOutputSupportedFor(Class)
+ */
+ public <T> Size[] getOutputSizes(final Class<T> klass) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get a list of sizes compatible with the requested image {@code format}.
+ *
+ * <p>The {@code format} should be a supported format (one of the formats returned by
+ * {@link #getOutputFormats}).</p>
+ *
+ * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
+ * @return
+ * an array of supported sizes,
+ * or {@code null} if the {@code format} is not a supported output
+ *
+ * @see ImageFormat
+ * @see PixelFormat
+ * @see #getOutputFormats
+ */
+ public Size[] getOutputSizes(final int format) {
+ try {
+ checkArgumentFormatSupported(format, /*output*/true);
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration}
+ * for the format/size combination (in nanoseconds).
+ *
+ * <p>{@code format} should be one of the ones returned by {@link #getOutputFormats()}.</p>
+ * <p>{@code size} should be one of the ones returned by
+ * {@link #getOutputSizes(int)}.</p>
+ *
+ * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
+ * @param size an output-compatible size
+ * @return a minimum frame duration {@code >=} 0 in nanoseconds
+ *
+ * @throws IllegalArgumentException if {@code format} or {@code size} was not supported
+ * @throws NullPointerException if {@code size} was {@code null}
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
+ * @see CaptureRequest#SENSOR_FRAME_DURATION
+ * @see ImageFormat
+ * @see PixelFormat
+ */
+ public long getOutputMinFrameDuration(final int format, final Size size) {
+ checkArgumentFormatSupported(format, /*output*/true);
+
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get the minimum {@link CaptureRequest#SENSOR_FRAME_DURATION frame duration}
+ * for the class/size combination (in nanoseconds).
+ *
+ * <p>This assumes a the {@code klass} is set up to use an implementation-defined format.
+ * For user-defined formats, use {@link #getOutputMinFrameDuration(int, Size)}.</p>
+ *
+ * <p>{@code klass} should be one of the ones which is supported by
+ * {@link #isOutputSupportedFor(Class)}.</p>
+ *
+ * <p>{@code size} should be one of the ones returned by
+ * {@link #getOutputSizes(int)}.</p>
+ *
+ * @param klass
+ * a class which is supported by {@link #isOutputSupportedFor(Class)} and has a
+ * non-empty array returned by {@link #getOutputSizes(Class)}
+ * @param size an output-compatible size
+ * @return a minimum frame duration {@code >=} 0 in nanoseconds
+ *
+ * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
+ * @throws NullPointerException if {@code size} or {@code klass} was {@code null}
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
+ * @see CaptureRequest#SENSOR_FRAME_DURATION
+ * @see ImageFormat
+ * @see PixelFormat
+ */
+ public <T> long getOutputMinFrameDuration(final Class<T> klass, final Size size) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get the {@link CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS stall duration}
+ * for the format/size combination (in nanoseconds).
+ *
+ * <p>{@code format} should be one of the ones returned by {@link #getOutputFormats()}.</p>
+ * <p>{@code size} should be one of the ones returned by
+ * {@link #getOutputSizes(int)}.</p>
+ *
+ * @param format an image format from {@link ImageFormat} or {@link PixelFormat}
+ * @param size an output-compatible size
+ * @return a stall duration {@code >=} 0 in nanoseconds
+ *
+ * @throws IllegalArgumentException if {@code format} or {@code size} was not supported
+ * @throws NullPointerException if {@code size} was {@code null}
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS
+ * @see ImageFormat
+ * @see PixelFormat
+ */
+ public long getOutputStallDuration(final int format, final Size size) {
+ checkArgumentFormatSupported(format, /*output*/true);
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Get the {@link CameraCharacteristics#SCALER_AVAILABLE_STALL_DURATIONS stall duration}
+ * for the class/size combination (in nanoseconds).
+ *
+ * <p>This assumes a the {@code klass} is set up to use an implementation-defined format.
+ * For user-defined formats, use {@link #getOutputMinFrameDuration(int, Size)}.</p>
+ *
+ * <p>{@code klass} should be one of the ones with a non-empty array returned by
+ * {@link #getOutputSizes(Class)}.</p>
+ *
+ * <p>{@code size} should be one of the ones returned by
+ * {@link #getOutputSizes(Class)}.</p>
+ *
+ * @param klass
+ * a class which is supported by {@link #isOutputSupportedFor(Class)} and has a
+ * non-empty array returned by {@link #getOutputSizes(Class)}
+ * @param size an output-compatible size
+ * @return a minimum frame duration {@code >=} 0 in nanoseconds
+ *
+ * @throws IllegalArgumentException if {@code klass} or {@code size} was not supported
+ * @throws NullPointerException if {@code size} or {@code klass} was {@code null}
+ *
+ * @see CameraCharacteristics#SCALER_AVAILABLE_MIN_FRAME_DURATIONS
+ * @see CaptureRequest#SENSOR_FRAME_DURATION
+ * @see ImageFormat
+ * @see PixelFormat
+ */
+ public <T> long getOutputStallDuration(final Class<T> klass, final Size size) {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
+
+ /**
+ * Check if this {@link StreamConfigurationMap} is equal to another
+ * {@link StreamConfigurationMap}.
+ *
+ * <p>Two vectors are only equal if and only if each of the respective elements is equal.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof StreamConfigurationMap) {
+ final StreamConfigurationMap other = (StreamConfigurationMap) obj;
+ // TODO: do we care about order?
+ return Arrays.equals(mConfigurations, other.mConfigurations) &&
+ Arrays.equals(mDurations, other.mDurations);
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ // TODO: do we care about order?
+ return HashCodeHelpers.hashCode(mConfigurations) ^ HashCodeHelpers.hashCode(mDurations);
+ }
+
+ // Check that the argument is supported by #getOutputFormats or #getInputFormats
+ private int checkArgumentFormatSupported(int format, boolean output) {
+ checkArgumentFormat(format);
+
+ int[] formats = output ? getOutputFormats() : getInputFormats();
+ for (int i = 0; i < formats.length; ++i) {
+ if (format == formats[i]) {
+ return format;
+ }
+ }
+
+ throw new IllegalArgumentException(String.format(
+ "format %x is not supported by this stream configuration map", format));
+ }
+
+ /**
+ * Ensures that the format is either user-defined or implementation defined.
+ *
+ * <p>Any invalid/undefined formats will raise an exception.</p>
+ *
+ * @param format image format
+ * @return the format
+ *
+ * @throws IllegalArgumentException if the format was invalid
+ */
+ static int checkArgumentFormatInternal(int format) {
+ if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+ return format;
+ }
+
+ return checkArgumentFormat(format);
+ }
+
+ /**
+ * Ensures that the format is user-defined in either ImageFormat or PixelFormat.
+ *
+ * <p>Any invalid/undefined formats will raise an exception, including implementation-defined.
+ * </p>
+ *
+ * <p>Note that {@code @hide} and deprecated formats will not pass this check.</p>
+ *
+ * @param format image format
+ * @return the format
+ *
+ * @throws IllegalArgumentException if the format was not user-defined
+ */
+ static int checkArgumentFormat(int format) {
+ if (!ImageFormat.isPublicFormat(format) && !PixelFormat.isPublicFormat(format)) {
+ throw new IllegalArgumentException(String.format(
+ "format %x was not defined in either ImageFormat or PixelFormat", format));
+ }
+
+ return format;
+ }
+
+ private static final int HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED = 0x22;
+
+ private final StreamConfiguration[] mConfigurations;
+ private final StreamConfigurationDuration[] mDurations;
+
+}
diff --git a/core/java/android/hardware/camera2/TonemapCurve.java b/core/java/android/hardware/camera2/TonemapCurve.java
new file mode 100644
index 0000000..ee20d68
--- /dev/null
+++ b/core/java/android/hardware/camera2/TonemapCurve.java
@@ -0,0 +1,290 @@
+/*
+ * 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.hardware.camera2;
+
+import static com.android.internal.util.Preconditions.*;
+
+import android.graphics.PointF;
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+import java.util.Arrays;
+
+/**
+ * Immutable class for describing a {@code 2 x M x 3} tonemap curve of floats.
+ *
+ * <p>This defines red, green, and blue curves that the {@link CameraDevice} will
+ * use as the tonemapping/contrast/gamma curve when {@link CaptureRequest#TONEMAP_MODE} is
+ * set to {@link CameraMetadata#TONEMAP_MODE_CONTRAST_CURVE}.</p>
+ *
+ * <p>The total number of points {@code (Pin, Pout)} for each color channel can be no more than
+ * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS}.</p>
+ *
+ * <p>The coordinate system for each point is within the inclusive range
+ * [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
+ *
+ * @see CaptureRequest#TONEMAP_CURVE_BLUE
+ * @see CaptureRequest#TONEMAP_CURVE_GREEN
+ * @see CaptureRequest#TONEMAP_CURVE_RED
+ * @see CameraMetadata#TONEMAP_MODE_CONTRAST_CURVE
+ * @see CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS
+ */
+public final class TonemapCurve {
+ /**
+ * Lower bound tonemap value corresponding to pure black for a single color channel.
+ */
+ public static final float LEVEL_BLACK = 0.0f;
+
+ /**
+ * Upper bound tonemap value corresponding to a pure white for a single color channel.
+ */
+ public static final float LEVEL_WHITE = 1.0f;
+
+ /**
+ * Number of elements in a {@code (Pin, Pout)} point;
+ */
+ public static final int POINT_SIZE = 2;
+
+ /**
+ * Index of the red color channel curve.
+ */
+ public static final int CHANNEL_RED = 0;
+ /**
+ * Index of the green color channel curve.
+ */
+ public static final int CHANNEL_GREEN = 1;
+ /**
+ * Index of the blue color channel curve.
+ */
+ public static final int CHANNEL_BLUE = 2;
+
+ /**
+ * Create a new immutable TonemapCurve instance.
+ *
+ * <p>Values are stored as a contiguous {@code (Pin, Pout}) point.</p>
+ *
+ * <p>All parameters may have independent length but should have at most
+ * {@link CameraCharacteristics#TONEMAP_MAX_CURVE_POINTS} * {@value #POINT_SIZE} elements.</p>
+ *
+ * <p>All sub-elements must be in the inclusive range of
+ * [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
+ *
+ * <p>This constructor copies the array contents and does not retain ownership of the array.</p>
+ *
+ * @param elements An array of elements whose length is {@code CHANNEL_COUNT * rows * columns}
+ *
+ * @throws IllegalArgumentException
+ * if the {@code elements} array length is invalid,
+ * if any of the subelems are not finite
+ * @throws NullPointerException
+ * if any of the parameters is {@code null}
+ *
+ * @hide
+ */
+ public TonemapCurve(float[] red, float[] green, float[] blue) {
+ // TODO: maxCurvePoints check?
+
+ checkNotNull(red, "red must not be null");
+ checkNotNull(green, "green must not be null");
+ checkNotNull(blue, "blue must not be null");
+
+ checkArgumentArrayLengthDivisibleBy(red, POINT_SIZE, "red");
+ checkArgumentArrayLengthDivisibleBy(green, POINT_SIZE, "green");
+ checkArgumentArrayLengthDivisibleBy(blue, POINT_SIZE, "blue");
+
+ checkArrayElementsInRange(red, LEVEL_BLACK, LEVEL_WHITE, "red");
+ checkArrayElementsInRange(green, LEVEL_BLACK, LEVEL_WHITE, "green");
+ checkArrayElementsInRange(blue, LEVEL_BLACK, LEVEL_WHITE, "blue");
+
+ mRed = Arrays.copyOf(red, red.length);
+ mGreen = Arrays.copyOf(green, green.length);
+ mBlue = Arrays.copyOf(blue, blue.length);
+ }
+
+ private static void checkArgumentArrayLengthDivisibleBy(float[] array,
+ int divisible, String arrayName) {
+ if (array.length % divisible != 0) {
+ throw new IllegalArgumentException(arrayName + " size must be divisible by "
+ + divisible);
+ }
+ }
+
+ private static int checkArgumentColorChannel(int colorChannel) {
+ switch (colorChannel) {
+ case CHANNEL_RED:
+ case CHANNEL_GREEN:
+ case CHANNEL_BLUE:
+ break;
+ default:
+ throw new IllegalArgumentException("colorChannel out of range");
+ }
+
+ return colorChannel;
+ }
+
+ /**
+ * Get the number of points stored in this tonemap curve for the specified color channel.
+ *
+ * @param colorChannel one of {@link #CHANNEL_RED}, {@link #CHANNEL_GREEN}, {@link #CHANNEL_BLUE}
+ * @return number of points stored in this tonemap for that color's curve (>= 0)
+ *
+ * @throws IllegalArgumentException if {@code colorChannel} was out of range
+ */
+ public int getPointCount(int colorChannel) {
+ checkArgumentColorChannel(colorChannel);
+
+ return getCurve(colorChannel).length / POINT_SIZE;
+ }
+
+ /**
+ * Get the point for a color channel at a specified index.
+ *
+ * <p>The index must be at least 0 but no greater than {@link #getPointCount(int)} for
+ * that {@code colorChannel}.</p>
+ *
+ * <p>All returned coordinates in the point are between the range of
+ * [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
+ *
+ * @param colorChannel {@link #CHANNEL_RED}, {@link #CHANNEL_GREEN}, or {@link #CHANNEL_BLUE}
+ * @param index at least 0 but no greater than {@code getPointCount(colorChannel)}
+ * @return the {@code (Pin, Pout)} pair mapping the tone for that index
+ *
+ * @throws IllegalArgumentException if {@code colorChannel} or {@code index} was out of range
+ *
+ * @see #LEVEL_BLACK
+ * @see #LEVEL_WHITE
+ */
+ public PointF getPoint(int colorChannel, int index) {
+ checkArgumentColorChannel(colorChannel);
+ if (index < 0 || index >= getPointCount(colorChannel)) {
+ throw new IllegalArgumentException("index out of range");
+ }
+
+ final float[] curve = getCurve(colorChannel);
+
+ final float pIn = curve[index * POINT_SIZE + OFFSET_POINT_IN];
+ final float pOut = curve[index * POINT_SIZE + OFFSET_POINT_OUT];
+
+ return new PointF(pIn, pOut);
+ }
+
+ /**
+ * Copy the color curve for a single color channel from this tonemap curve into the destination.
+ *
+ * <p>
+ * <!--The output is encoded the same as in the constructor -->
+ * Values are stored as packed {@code (Pin, Pout}) points, and there are a total of
+ * {@link #getPointCount} points for that respective channel.</p>
+ *
+ * <p>All returned coordinates are between the range of
+ * [{@value #LEVEL_BLACK}, {@value #LEVEL_WHITE}].</p>
+ *
+ * @param destination
+ * an array big enough to hold at least {@link #getPointCount} {@code *}
+ * {@link #POINT_SIZE} elements after the {@code offset}
+ * @param offset
+ * a non-negative offset into the array
+ * @throws NullPointerException
+ * If {@code destination} was {@code null}
+ * @throws IllegalArgumentException
+ * If offset was negative
+ * @throws ArrayIndexOutOfBoundsException
+ * If there's not enough room to write the elements at the specified destination and
+ * offset.
+ *
+ * @see CaptureRequest#TONEMAP_CURVE_BLUE
+ * @see CaptureRequest#TONEMAP_CURVE_RED
+ * @see CaptureRequest#TONEMAP_CURVE_GREEN
+ * @see #LEVEL_BLACK
+ * @see #LEVEL_WHITE
+ */
+ public void copyColorCurve(int colorChannel, float[] destination,
+ int offset) {
+ checkArgumentNonnegative(offset, "offset must not be negative");
+ checkNotNull(destination, "destination must not be null");
+
+ if (destination.length + offset < getPointCount(colorChannel) * POINT_SIZE) {
+ throw new ArrayIndexOutOfBoundsException("destination too small to fit elements");
+ }
+
+ float[] curve = getCurve(colorChannel);
+ System.arraycopy(curve, /*srcPos*/0, destination, offset, curve.length);
+ }
+
+ /**
+ * Check if this TonemapCurve is equal to another TonemapCurve.
+ *
+ * <p>Two matrices are equal if and only if all of their elements are
+ * {@link Object#equals equal}.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof TonemapCurve) {
+ final TonemapCurve other = (TonemapCurve) obj;
+ return Arrays.equals(mRed, other.mRed) &&
+ Arrays.equals(mGreen, other.mGreen) &&
+ Arrays.equals(mBlue, other.mBlue);
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ if (mHashCalculated) {
+ // Avoid re-calculating hash. Data is immutable so this is both legal and faster.
+ return mHashCode;
+ }
+
+ mHashCode = HashCodeHelpers.hashCode(mRed, mGreen, mBlue);
+ mHashCalculated = true;
+
+ return mHashCode;
+ }
+
+ private float[] getCurve(int colorChannel) {
+ switch (colorChannel) {
+ case CHANNEL_RED:
+ return mRed;
+ case CHANNEL_GREEN:
+ return mGreen;
+ case CHANNEL_BLUE:
+ return mBlue;
+ default:
+ throw new AssertionError("colorChannel out of range");
+ }
+ }
+
+ private final static int OFFSET_POINT_IN = 0;
+ private final static int OFFSET_POINT_OUT = 1;
+
+ private final float[] mRed;
+ private final float[] mGreen;
+ private final float[] mBlue;
+
+ private int mHashCode;
+ private boolean mHashCalculated = false;
+};
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java
index 40a7905..988f8f9 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDevice.java
@@ -647,7 +647,7 @@
* should have arrived. The following line checks whether this holds.
*/
if (frameNumber != mCompletedFrameNumber + 1) {
- throw new AssertionError(String.format(
+ Log.e(TAG, String.format(
"result frame number %d comes out of order, should be %d + 1",
frameNumber, mCompletedFrameNumber));
}
diff --git a/core/java/android/hardware/camera2/impl/HashCodeHelpers.java b/core/java/android/hardware/camera2/impl/HashCodeHelpers.java
new file mode 100644
index 0000000..2d63827
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/HashCodeHelpers.java
@@ -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.
+ */
+
+package android.hardware.camera2.impl;
+
+/**
+ * Provide hashing functions using the Modified Bernstein hash
+ */
+public final class HashCodeHelpers {
+
+ /**
+ * Hash every element uniformly using the Modified Bernstein hash.
+ *
+ * <p>Useful to implement a {@link Object#hashCode} for uniformly distributed data.</p>
+ *
+ * @param array a non-{@code null} array of integers
+ *
+ * @return the numeric hash code
+ */
+ public static int hashCode(int[] array) {
+ if (array == null) {
+ return 0;
+ }
+
+ /*
+ * Note that we use 31 here instead of 33 since it's preferred in Effective Java
+ * and used elsewhere in the runtime (e.g. Arrays#hashCode)
+ *
+ * That being said 33 and 31 are nearly identical in terms of their usefulness
+ * according to http://svn.apache.org/repos/asf/apr/apr/trunk/tables/apr_hash.c
+ */
+ int h = 1;
+ for (int x : array) {
+ // Strength reduction; in case the compiler has illusions about divisions being faster
+ h = ((h << 5) - h) ^ x; // (h * 31) XOR x
+ }
+
+ return h;
+ }
+
+ /**
+ * Hash every element uniformly using the Modified Bernstein hash.
+ *
+ * <p>Useful to implement a {@link Object#hashCode} for uniformly distributed data.</p>
+ *
+ * @param array a non-{@code null} array of floats
+ *
+ * @return the numeric hash code
+ */
+ public static int hashCode(float[] array) {
+ if (array == null) {
+ return 0;
+ }
+
+ int h = 1;
+ for (float f : array) {
+ int x = Float.floatToIntBits(f);
+ h = ((h << 5) - h) ^ x; // (h * 31) XOR x
+ }
+
+ return h;
+ }
+
+ /**
+ * Hash every element uniformly using the Modified Bernstein hash.
+ *
+ * <p>Useful to implement a {@link Object#hashCode} for uniformly distributed data.</p>
+ *
+ * @param array a non-{@code null} array of objects
+ *
+ * @return the numeric hash code
+ */
+ public static <T> int hashCode(T[] array) {
+ if (array == null) {
+ return 0;
+ }
+
+ int h = 1;
+ for (T o : array) {
+ int x = (o == null) ? 0 : o.hashCode();
+ h = ((h << 5) - h) ^ x; // (h * 31) XOR x
+ }
+
+ return h;
+ }
+
+ public static <T> int hashCode(T a) {
+ return (a == null) ? 0 : a.hashCode();
+ }
+
+ public static <T> int hashCode(T a, T b) {
+ int h = hashCode(a);
+
+ int x = (b == null) ? 0 : b.hashCode();
+ h = ((h << 5) - h) ^ x; // (h * 31) XOR x
+
+ return h;
+ }
+
+ public static <T> int hashCode(T a, T b, T c) {
+ int h = hashCode(a, b);
+
+ int x = (a == null) ? 0 : a.hashCode();
+ h = ((h << 5) - h) ^ x; // (h * 31) XOR x
+
+ return h;
+ }
+
+ public static int hashCode(int x) {
+ return hashCode(new int[] { x } );
+ }
+
+ public static int hashCode(int x, int y) {
+ return hashCode(new int[] { x, y } );
+ }
+
+ public static int hashCode(int x, int y, int z) {
+ return hashCode(new int[] { x, y, z } );
+ }
+
+ public static int hashCode(int x, int y, int z, int w) {
+ return hashCode(new int[] { x, y, z, w } );
+ }
+
+ public static int hashCode(int x, int y, int z, int w, int t) {
+ return hashCode(new int[] { x, y, z, w, t } );
+ }
+
+
+}
diff --git a/core/java/android/hardware/hdmi/HdmiCec.java b/core/java/android/hardware/hdmi/HdmiCec.java
index eafaed6..7213c78 100644
--- a/core/java/android/hardware/hdmi/HdmiCec.java
+++ b/core/java/android/hardware/hdmi/HdmiCec.java
@@ -160,6 +160,8 @@
public static final int MESSAGE_SET_EXTERNAL_TIMER = 0xA2;
public static final int MESSAGE_ABORT = 0xFF;
+ public static final int UNKNOWN_VENDOR_ID = 0xFFFFFF;
+
public static final int POWER_STATUS_UNKNOWN = -1;
public static final int POWER_STATUS_ON = 0;
public static final int POWER_STATUS_STANDBY = 1;
diff --git a/core/java/android/hardware/hdmi/HdmiCecMessage.java b/core/java/android/hardware/hdmi/HdmiCecMessage.java
index be94d97..ddaf870 100644
--- a/core/java/android/hardware/hdmi/HdmiCecMessage.java
+++ b/core/java/android/hardware/hdmi/HdmiCecMessage.java
@@ -19,6 +19,8 @@
import android.os.Parcel;
import android.os.Parcelable;
+import libcore.util.EmptyArray;
+
import java.util.Arrays;
/**
@@ -28,6 +30,8 @@
*/
public final class HdmiCecMessage implements Parcelable {
+ public static final byte[] EMPTY_PARAM = EmptyArray.BYTE;
+
private static final int MAX_MESSAGE_LENGTH = 16;
private final int mSource;
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index e6dbcd0..f6438b4 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -654,17 +654,20 @@
return false;
}
- @Override
- public void onCreate() {
- mTheme = getResources().selectSystemTheme(mTheme, getApplicationInfo().targetSdkVersion,
- com.android.internal.R.array.system_theme_sdks,
- com.android.internal.R.array.system_theme_ime_styles);
+ @Override public void onCreate() {
+ mTheme = Resources.selectSystemTheme(mTheme,
+ 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();
mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
mInflater = (LayoutInflater)getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
- mWindow = new SoftInputWindow(this, mTheme, mDispatcherState);
+ mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,
+ false);
if (mHardwareAccelerated) {
mWindow.getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
}
diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java
index df1afee..a9bace1 100644
--- a/core/java/android/inputmethodservice/SoftInputWindow.java
+++ b/core/java/android/inputmethodservice/SoftInputWindow.java
@@ -30,11 +30,20 @@
* method window. It will be displayed along the edge of the screen, moving
* the application user interface away from it so that the focused item is
* always visible.
+ * @hide
*/
-class SoftInputWindow extends Dialog {
+public class SoftInputWindow extends Dialog {
+ final String mName;
+ final Callback mCallback;
+ final KeyEvent.Callback mKeyEventCallback;
final KeyEvent.DispatcherState mDispatcherState;
+ final boolean mTakesFocus;
private final Rect mBounds = new Rect();
-
+
+ public interface Callback {
+ public void onBackPressed();
+ }
+
public void setToken(IBinder token) {
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.token = token;
@@ -53,10 +62,15 @@
* using styles. This theme is applied on top of the current theme in
* <var>context</var>. If 0, the default dialog theme will be used.
*/
- public SoftInputWindow(Context context, int theme,
- KeyEvent.DispatcherState dispatcherState) {
+ public SoftInputWindow(Context context, String name, int theme, Callback callback,
+ KeyEvent.Callback keyEventCallback, KeyEvent.DispatcherState dispatcherState,
+ boolean takesFocus) {
super(context, theme);
+ mName = name;
+ mCallback = callback;
+ mKeyEventCallback = keyEventCallback;
mDispatcherState = dispatcherState;
+ mTakesFocus = takesFocus;
initDockWindow();
}
@@ -148,11 +162,47 @@
}
}
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (mKeyEventCallback != null && mKeyEventCallback.onKeyDown(keyCode, event)) {
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+ if (mKeyEventCallback != null && mKeyEventCallback.onKeyLongPress(keyCode, event)) {
+ return true;
+ }
+ return super.onKeyLongPress(keyCode, event);
+ }
+
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (mKeyEventCallback != null && mKeyEventCallback.onKeyUp(keyCode, event)) {
+ return true;
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+
+ public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
+ if (mKeyEventCallback != null && mKeyEventCallback.onKeyMultiple(keyCode, count, event)) {
+ return true;
+ }
+ return super.onKeyMultiple(keyCode, count, event);
+ }
+
+ public void onBackPressed() {
+ if (mCallback != null) {
+ mCallback.onBackPressed();
+ } else {
+ super.onBackPressed();
+ }
+ }
+
private void initDockWindow() {
WindowManager.LayoutParams lp = getWindow().getAttributes();
lp.type = WindowManager.LayoutParams.TYPE_INPUT_METHOD;
- lp.setTitle("InputMethod");
+ lp.setTitle(mName);
lp.gravity = Gravity.BOTTOM;
lp.width = -1;
@@ -161,11 +211,19 @@
//lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
getWindow().setAttributes(lp);
- getWindow().setFlags(
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
+
+ int windowSetFlags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+ int windowModFlags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
- WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+ WindowManager.LayoutParams.FLAG_DIM_BEHIND;
+
+ if (!mTakesFocus) {
+ windowSetFlags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+ } else {
+ windowSetFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+ windowModFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+ }
+
+ getWindow().setFlags(windowSetFlags, windowModFlags);
}
}
diff --git a/core/java/android/net/INetworkScoreCache.aidl b/core/java/android/net/INetworkScoreCache.aidl
new file mode 100644
index 0000000..35601ce
--- /dev/null
+++ b/core/java/android/net/INetworkScoreCache.aidl
@@ -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 android.net;
+
+import android.net.ScoredNetwork;
+
+/**
+ * A service which stores a subset of scored networks from the active network scorer.
+ *
+ * <p>To be implemented by network subsystems (e.g. Wi-Fi). NetworkScoreService will propagate
+ * scores down to each subsystem depending on the network type. Implementations may register for
+ * a given network type by calling NetworkScoreManager.registerNetworkSubsystem.
+ *
+ * <p>A proper implementation should throw SecurityException whenever the caller is not privileged.
+ * It may request scores by calling NetworkScoreManager#requestScores(NetworkKey[]); a call to
+ * updateScores may follow but may not depending on the active scorer's implementation, and in
+ * general this method may be called at any time.
+ *
+ * <p>Implementations should also override dump() so that "adb shell dumpsys network_score" includes
+ * the current scores for each network for debugging purposes.
+ * @hide
+ */
+interface INetworkScoreCache
+{
+ void updateScores(in List<ScoredNetwork> networks);
+
+ void clearScores();
+}
+
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
index a72d9a0..626bd2a 100644
--- a/core/java/android/net/INetworkScoreService.aidl
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -16,6 +16,7 @@
package android.net;
+import android.net.INetworkScoreCache;
import android.net.ScoredNetwork;
/**
@@ -34,8 +35,7 @@
/**
* Clear all scores.
* @return whether the clear was successful.
- * @throws SecurityException if the caller is neither the current active scorer nor the scorer
- * manager.
+ * @throws SecurityException if the caller is neither the current active scorer nor the system.
*/
boolean clearScores();
@@ -43,7 +43,19 @@
* Set the active scorer and clear existing scores.
* @param packageName the package name of the new scorer to use.
* @return true if the operation succeeded, or false if the new package is not a valid scorer.
- * @throws SecurityException if the caller is not the scorer manager.
+ * @throws SecurityException if the caller is not the system.
*/
boolean setActiveScorer(in String packageName);
+
+ /**
+ * Register a network subsystem for scoring.
+ *
+ * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
+ * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
+ * @throws SecurityException if the caller is not the system.
+ * @throws IllegalArgumentException if a score cache is already registed for this type.
+ * @hide
+ */
+ void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache);
+
}
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 6dd56d9..352512e 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -19,6 +19,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
+import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -101,7 +102,7 @@
* determine the current scorer and offer the user the ability to select a different scorer via
* the {@link #ACTION_CHANGE_ACTIVE} intent.
* @return the full package name of the current active scorer, or null if there is no active
- * scorer.
+ * scorer.
*/
public String getActiveScorerPackage() {
return NetworkScorerAppManager.getActiveScorer(mContext);
@@ -151,8 +152,8 @@
*
* @return true if the operation succeeded, or false if the new package is not a valid scorer.
* @throws SecurityException if the caller does not hold the
- * {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission indicating that
- * it can manage scorer applications.
+ * {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission indicating
+ * that it can manage scorer applications.
* @hide
*/
public boolean setActiveScorer(String packageName) throws SecurityException {
@@ -162,4 +163,44 @@
return false;
}
}
+
+ /**
+ * Request scoring for networks.
+ *
+ * <p>Note that this is just a helper method to assemble the broadcast, and will run in the
+ * calling process.
+ *
+ * @return true if the broadcast was sent, or false if there is no active scorer.
+ * @throws SecurityException if the caller does not hold the
+ * {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission.
+ * @hide
+ */
+ public boolean requestScores(NetworkKey[] networks) throws SecurityException {
+ String activeScorer = getActiveScorerPackage();
+ if (activeScorer == null) {
+ return false;
+ }
+ Intent intent = new Intent(ACTION_SCORE_NETWORKS);
+ intent.setPackage(activeScorer);
+ intent.putExtra(EXTRA_NETWORKS_TO_SCORE, networks);
+ mContext.sendBroadcast(intent);
+ return true;
+ }
+
+ /**
+ * Register a network score cache.
+ *
+ * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
+ * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
+ * @throws SecurityException if the caller does not hold the
+ * {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission.
+ * @throws IllegalArgumentException if a score cache is already registered for this type.
+ * @hide
+ */
+ public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
+ try {
+ mService.registerNetworkScoreCache(networkType, scoreCache);
+ } catch (RemoteException e) {
+ }
+ }
}
diff --git a/core/java/android/net/RssiCurve.java b/core/java/android/net/RssiCurve.java
index 33e81c2..dd744d3 100644
--- a/core/java/android/net/RssiCurve.java
+++ b/core/java/android/net/RssiCurve.java
@@ -98,6 +98,27 @@
}
/**
+ * Lookup the score for a given RSSI value.
+ *
+ * @param rssi The RSSI to lookup. If the RSSI falls below the start of the curve, the score at
+ * the start of the curve will be returned. If it falls after the end of the curve, the
+ * score at the end of the curve will be returned.
+ * @return the score for the given RSSI.
+ */
+ public byte lookupScore(int rssi) {
+ int index = (rssi - start) / bucketWidth;
+
+ // Snap the index to the closest bucket if it falls outside the curve.
+ if (index < 0) {
+ index = 0;
+ } else if (index > rssiBuckets.length - 1) {
+ index = rssiBuckets.length - 1;
+ }
+
+ return rssiBuckets[index];
+ }
+
+ /**
* Determine if two RSSI curves are defined in the same way.
*
* <p>Note that two curves can be equivalent but defined differently, e.g. if one bucket in one
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9e9820f..e78ce33 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -175,6 +175,8 @@
private static final String POWER_USE_ITEM_DATA = "pwi";
private static final String DISCHARGE_STEP_DATA = "dsd";
private static final String CHARGE_STEP_DATA = "csd";
+ private static final String DISCHARGE_TIME_REMAIN_DATA = "dtr";
+ private static final String CHARGE_TIME_REMAIN_DATA = "ctr";
private final StringBuilder mFormatBuilder = new StringBuilder(32);
private final Formatter mFormatter = new Formatter(mFormatBuilder);
@@ -909,6 +911,8 @@
*/
public abstract int getScreenOnCount(int which);
+ public abstract long getInteractiveTime(long elapsedRealtimeUs, int which);
+
public static final int SCREEN_BRIGHTNESS_DARK = 0;
public static final int SCREEN_BRIGHTNESS_DIM = 1;
public static final int SCREEN_BRIGHTNESS_MEDIUM = 2;
@@ -934,8 +938,6 @@
public abstract long getScreenBrightnessTime(int brightnessBin,
long elapsedRealtimeUs, int which);
- public abstract int getInputEventCount(int which);
-
/**
* Returns the time in microseconds that the phone has been on while the device was
* running on battery.
@@ -1569,6 +1571,7 @@
final long totalRealtime = computeRealtime(rawRealtime, which);
final long totalUptime = computeUptime(rawUptime, which);
final long screenOnTime = getScreenOnTime(rawRealtime, which);
+ final long interactiveTime = getInteractiveTime(rawRealtime, which);
final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
final long wifiOnTime = getWifiOnTime(rawRealtime, which);
final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
@@ -1637,8 +1640,8 @@
wifiRunningTime / 1000, bluetoothOnTime / 1000,
mobileRxTotalBytes, mobileTxTotalBytes, wifiRxTotalBytes, wifiTxTotalBytes,
fullWakeLockTimeTotal, partialWakeLockTimeTotal,
- getInputEventCount(which), getMobileRadioActiveTime(rawRealtime, which),
- getMobileRadioActiveAdjustedTime(which));
+ 0 /*legacy input event count*/, getMobileRadioActiveTime(rawRealtime, which),
+ getMobileRadioActiveAdjustedTime(which), interactiveTime / 1000);
// Dump screen brightness stats
Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
@@ -2011,6 +2014,7 @@
sb.append("realtime, ");
formatTimeMs(sb, totalUptime / 1000);
sb.append("uptime");
+ pw.println(sb.toString());
if (batteryTimeRemaining >= 0) {
sb.setLength(0);
sb.append(prefix);
@@ -2029,16 +2033,25 @@
pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss", getStartClockTime()).toString());
final long screenOnTime = getScreenOnTime(rawRealtime, which);
+ final long interactiveTime = getInteractiveTime(rawRealtime, which);
final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which);
final long wifiOnTime = getWifiOnTime(rawRealtime, which);
final long bluetoothOnTime = getBluetoothOnTime(rawRealtime, which);
sb.setLength(0);
sb.append(prefix);
+ sb.append(" Interactive: "); formatTimeMs(sb, interactiveTime / 1000);
+ sb.append("("); sb.append(formatRatioLocked(interactiveTime, whichBatteryRealtime));
+ sb.append(")");
+ pw.println(sb.toString());
+ sb.setLength(0);
+ sb.append(prefix);
sb.append(" Screen on: "); formatTimeMs(sb, screenOnTime / 1000);
sb.append("("); sb.append(formatRatioLocked(screenOnTime, whichBatteryRealtime));
sb.append(") "); sb.append(getScreenOnCount(which));
- sb.append("x, Input events: "); sb.append(getInputEventCount(which));
+ sb.append("x, Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000);
+ sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime));
+ sb.append(")");
pw.println(sb.toString());
if (phoneOnTime != 0) {
sb.setLength(0);
@@ -2897,7 +2910,7 @@
}
}
if (!didWake && wakelockTag != null) {
- pw.print(longNames ? "wake_lock=" : "w=");
+ pw.print(longNames ? " wake_lock=" : ",w=");
if (longNames) {
UserHandle.formatUid(pw, wakelockTag.uid);
pw.print(":\"");
@@ -3076,7 +3089,7 @@
HISTORY_STATE2_DESCRIPTIONS, !checkin);
if (rec.wakeReasonTag != null) {
if (checkin) {
- pw.print(",Wr=");
+ pw.print(",wr=");
pw.print(rec.wakeReasonTag.poolIdx);
} else {
pw.print(" wake_reason=");
@@ -3423,8 +3436,21 @@
if (!filtering) {
dumpDurationSteps(pw, DISCHARGE_STEP_DATA, getDischargeStepDurationsArray(),
getNumDischargeStepDurations(), true);
+ String[] lineArgs = new String[1];
+ long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
+ if (timeRemaining >= 0) {
+ lineArgs[0] = Long.toString(timeRemaining);
+ dumpLine(pw, 0 /* uid */, "i" /* category */, DISCHARGE_TIME_REMAIN_DATA,
+ (Object[])lineArgs);
+ }
dumpDurationSteps(pw, CHARGE_STEP_DATA, getChargeStepDurationsArray(),
getNumChargeStepDurations(), true);
+ timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
+ if (timeRemaining >= 0) {
+ lineArgs[0] = Long.toString(timeRemaining);
+ dumpLine(pw, 0 /* uid */, "i" /* category */, CHARGE_TIME_REMAIN_DATA,
+ (Object[])lineArgs);
+ }
}
if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ab06230..d5a3bcb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3480,6 +3480,12 @@
"lock_screen_appwidget_ids";
/**
+ * List of enrolled fingerprint identifiers (comma-delimited).
+ * @hide
+ */
+ public static final String USER_FINGERPRINT_IDS = "user_fingerprint_ids";
+
+ /**
* Id of the appwidget shown on the lock screen when appwidgets are disabled.
* @hide
*/
@@ -4395,6 +4401,13 @@
public static final String ANR_SHOW_BACKGROUND = "anr_show_background";
/**
+ * (Experimental). If nonzero, WebView uses data reduction proxy to save network
+ * bandwidth. Otherwise, WebView does not use data reduction proxy.
+ * @hide
+ */
+ public static final String WEBVIEW_DATA_REDUCTION_PROXY = "webview_data_reduction_proxy";
+
+ /**
* The {@link ComponentName} string of the service to be used as the voice recognition
* service.
*
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 2303d65..b02a79d 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -300,10 +300,6 @@
public void onDetachedFromWindow() {
}
- @Override
- public void onWindowDismissed() {
- }
-
/** {@inheritDoc} */
@Override
public void onPanelClosed(int featureId, Menu menu) {
diff --git a/core/java/android/service/fingerprint/FingerprintManager.java b/core/java/android/service/fingerprint/FingerprintManager.java
new file mode 100644
index 0000000..0d14c59
--- /dev/null
+++ b/core/java/android/service/fingerprint/FingerprintManager.java
@@ -0,0 +1,200 @@
+/**
+ * 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.fingerprint;
+
+import android.app.ActivityManagerNative;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+
+/**
+ * A class that coordinates access to the fingerprint hardware.
+ */
+
+public class FingerprintManager {
+ private static final String TAG = "FingerprintManager";
+ protected static final boolean DEBUG = true;
+ private static final String FINGERPRINT_SERVICE_PACKAGE = "com.android.service.fingerprint";
+ private static final String FINGERPRINT_SERVICE_CLASS =
+ "com.android.service.fingerprint.FingerprintService";
+ private static final int MSG_ENROLL_RESULT = 100;
+ private static final int MSG_SCANNED = 101;
+ private static final int MSG_ERROR = 102;
+ private static final int MSG_REMOVED = 103;
+
+ public static final int FINGERPRINT_ERROR_NO_RECEIVER = -10;
+ public static final int FINGERPRINT_ERROR = -1; // One of the error messages below.
+
+ // Progress messages.
+ public static final int FINGERPRINT_SCANNED = 1;
+ public static final int FINGERPRINT_TEMPLATE_ENROLLING = 2;
+ public static final int FINGERPRINT_TEMPLATE_REMOVED = 4;
+
+ // Error messages. Must agree with fingerprint HAL definitions.
+ public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1;
+ public static final int FINGERPRINT_ERROR_BAD_CAPTURE = 2;
+ public static final int FINGERPRINT_ERROR_TIMEOUT = 3;
+ public static final int FINGERPRINT_ERROR_NO_SPACE = 4;
+
+ private IFingerprintService mService;
+ private FingerprintManagerReceiver mClientReceiver;
+
+ private Handler mHandler = new Handler() {
+ public void handleMessage(android.os.Message msg) {
+ if (mClientReceiver != null) {
+ switch(msg.what) {
+ case MSG_ENROLL_RESULT:
+ mClientReceiver.onEnrollResult(msg.arg1, msg.arg2);
+ break;
+ case MSG_SCANNED:
+ mClientReceiver.onScanned(msg.arg1, msg.arg2);
+ break;
+ case MSG_ERROR:
+ mClientReceiver.onError(msg.arg1);
+ break;
+ case MSG_REMOVED:
+ mClientReceiver.onRemoved(msg.arg1);
+ }
+ }
+ }
+ };
+
+ public FingerprintManager(Context context) {
+ // Connect to service...
+ Intent intent = new Intent();
+ intent.setClassName(FINGERPRINT_SERVICE_PACKAGE, FINGERPRINT_SERVICE_CLASS);
+ if (!context.bindServiceAsUser(intent, mFingerprintConnection,
+ Context.BIND_AUTO_CREATE, UserHandle.CURRENT_OR_SELF)) {
+ if (DEBUG) Log.v(TAG, "Can't bind to " + FINGERPRINT_SERVICE_CLASS);
+ }
+ }
+
+ private final ServiceConnection mFingerprintConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (DEBUG) Log.v(TAG, "Connected to FingerprintService");
+ mService = IFingerprintService.Stub.asInterface(service);
+ try {
+ mService.startListening(mServiceReceiver, getCurrentUserId());
+ } catch (RemoteException e) {
+ if (DEBUG) Log.v(TAG, "Failed to set callback", e);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ if (DEBUG) Log.v(TAG, "Disconnected from FingerprintService");
+ mService = null;
+ }
+ };
+
+ private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
+
+ public void onEnrollResult(int fingerprintId, int remaining) {
+ mHandler.obtainMessage(MSG_ENROLL_RESULT, fingerprintId, remaining).sendToTarget();
+ }
+
+ public void onScanned(int fingerprintId, int confidence) {
+ mHandler.obtainMessage(MSG_SCANNED, fingerprintId, confidence)
+ .sendToTarget();;
+ }
+
+ public void onError(int error) {
+ mHandler.obtainMessage(MSG_ERROR, error, 0).sendToTarget();
+ }
+
+ public void onRemoved(int fingerprintId) {
+ mHandler.obtainMessage(MSG_REMOVED, fingerprintId, 0).sendToTarget();
+ }
+ };
+
+ /**
+ * Start the enrollment process. Timeout dictates how long to wait for the user to
+ * enroll a fingerprint.
+ *
+ * @param timeout
+ */
+ public void enroll(long timeout) {
+ if (mServiceReceiver == null) {
+ throw new IllegalStateException("enroll: Call registerCallback() first");
+ }
+ if (mService != null) try {
+ mService.enroll(timeout, getCurrentUserId());
+ } catch (RemoteException e) {
+ Log.v(TAG, "Remote exception while enrolling: ", e);
+ }
+ }
+
+ /**
+ * Remove the given fingerprintId from the system. FingerprintId of 0 has special meaning
+ * which is to delete all fingerprint data for the current user. Use with caution.
+ * @param fingerprintId
+ */
+ public void remove(int fingerprintId) {
+ if (mService != null) try {
+ mService.remove(fingerprintId, getCurrentUserId());
+ } catch (RemoteException e) {
+ Log.v(TAG, "Remote exception during remove of fingerprintId: " + fingerprintId, e);
+ }
+ }
+
+ /**
+ * Starts listening for fingerprint events. When a finger is scanned or recognized, the
+ * client will be notified via the callback.
+ */
+ public void startListening(FingerprintManagerReceiver receiver) {
+ mClientReceiver = receiver;
+ if (mService != null) {
+ try {
+ mService.startListening(mServiceReceiver, getCurrentUserId());
+ } catch (RemoteException e) {
+ Log.v(TAG, "Remote exception in startListening(): ", e);
+ }
+ }
+ }
+
+ private int getCurrentUserId() {
+ try {
+ return ActivityManagerNative.getDefault().getCurrentUser().id;
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to get current user id\n");
+ return UserHandle.USER_NULL;
+ }
+ }
+
+ /**
+ * Stops the client from listening to fingerprint events.
+ */
+ public void stopListening() {
+ mClientReceiver = null;
+ if (mService != null) {
+ try {
+ mService.stopListening(getCurrentUserId());
+ } catch (RemoteException e) {
+ Log.v(TAG, "Remote exception in stopListening(): ", e);
+ }
+ } else {
+ Log.w(TAG, "stopListening(): Service not connected!");
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/java/android/service/fingerprint/FingerprintManagerReceiver.java b/core/java/android/service/fingerprint/FingerprintManagerReceiver.java
new file mode 100644
index 0000000..34f1655
--- /dev/null
+++ b/core/java/android/service/fingerprint/FingerprintManagerReceiver.java
@@ -0,0 +1,59 @@
+package android.service.fingerprint;
+/**
+ * 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.
+ */
+
+public class FingerprintManagerReceiver {
+ /**
+ * Fingerprint enrollment progress update. Enrollment is considered complete if
+ * remaining hits 0 without {@link #onError(int)} being called.
+ *
+ * @param fingerprintId the fingerprint we're currently enrolling
+ * @param remaining the number of samples required to complete enrollment. It's up to
+ * the hardware to define what each step in enrollment means. Some hardware
+ * requires multiple samples of the same part of the finger. Others require sampling of
+ * different parts of the finger. The enrollment flow can use remaining to
+ * mean "step x" of the process or "just need another sample."
+ */
+ public void onEnrollResult(int fingerprintId, int remaining) { }
+
+ /**
+ * Fingerprint scan detected. Most clients will use this function to detect a fingerprint
+ *
+ * @param fingerprintId is the finger the hardware has detected.
+ * @param confidence from 0 (no confidence) to 65535 (high confidence). Fingerprint 0 has
+ * special meaning - the finger wasn't recognized.
+ */
+ public void onScanned(int fingerprintId, int confidence) { }
+
+ /**
+ * An error was detected during scan or enrollment. One of
+ * {@link FingerprintManager#FINGERPRINT_ERROR_HW_UNAVAILABLE},
+ * {@link FingerprintManager#FINGERPRINT_ERROR_BAD_CAPTURE} or
+ * {@link FingerprintManager#FINGERPRINT_ERROR_TIMEOUT}
+ * {@link FingerprintManager#FINGERPRINT_ERROR_NO_SPACE}
+ *
+ * @param error one of the above error codes
+ */
+ public void onError(int error) { }
+
+ /**
+ * The given fingerprint template was successfully removed by the driver.
+ * See {@link FingerprintManager#remove(int)}
+ *
+ * @param fingerprintId id of template to remove.
+ */
+ public void onRemoved(int fingerprintId) { }
+}
\ No newline at end of file
diff --git a/core/java/android/service/fingerprint/FingerprintService.java b/core/java/android/service/fingerprint/FingerprintService.java
new file mode 100644
index 0000000..c7fa7cd
--- /dev/null
+++ b/core/java/android/service/fingerprint/FingerprintService.java
@@ -0,0 +1,219 @@
+/**
+ * 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.fingerprint;
+
+import android.app.Service;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+import java.util.HashMap;
+
+/**
+ * A service to manage multiple clients that want to access the fingerprint HAL API.
+ * The service is responsible for maintaining a list of clients and dispatching all
+ * fingerprint -related events.
+ *
+ * @hide
+ */
+public class FingerprintService extends Service {
+ private final String TAG = FingerprintService.class.getSimpleName() +
+ "[" + getClass().getSimpleName() + "]";
+ private static final boolean DEBUG = true;
+ HashMap<IFingerprintServiceReceiver, ClientData> mClients =
+ new HashMap<IFingerprintServiceReceiver, ClientData>();
+
+ private static final int MSG_NOTIFY = 10;
+
+ Handler mHandler = new Handler() {
+ public void handleMessage(android.os.Message msg) {
+ switch (msg.what) {
+ case MSG_NOTIFY:
+ handleNotify(msg.arg1, msg.arg2, (Integer) msg.obj);
+ break;
+
+ default:
+ Slog.w(TAG, "Unknown message:" + msg.what);
+ }
+ }
+ };
+
+ private static final int STATE_IDLE = 0;
+ private static final int STATE_LISTENING = 1;
+ private static final int STATE_ENROLLING = 2;
+ private static final int STATE_DELETING = 3;
+ private static final long MS_PER_SEC = 1000;
+
+ private static final class ClientData {
+ public IFingerprintServiceReceiver receiver;
+ int state;
+ int userId;
+ }
+
+ @Override
+ public final IBinder onBind(Intent intent) {
+ if (DEBUG) Slog.v(TAG, "onBind() intent = " + intent);
+ return new FingerprintServiceWrapper();
+ }
+
+ // JNI methods to communicate from FingerprintManagerService to HAL
+ native int nativeEnroll(int timeout);
+ native int nativeRemove(int fingerprintId);
+
+ // JNI methods for communicating from HAL to clients
+ void notify(int msg, int arg1, int arg2) {
+ mHandler.obtainMessage(MSG_NOTIFY, msg, arg1, arg2).sendToTarget();
+ }
+
+ void handleNotify(int msg, int arg1, int arg2) {
+ for (int i = 0; i < mClients.size(); i++) {
+ ClientData clientData = mClients.get(i);
+ switch (msg) {
+ case FingerprintManager.FINGERPRINT_ERROR: {
+ if (clientData.state != STATE_IDLE) {
+ // FINGERPRINT_ERROR_HW_UNAVAILABLE
+ // FINGERPRINT_ERROR_BAD_CAPTURE
+ // FINGERPRINT_ERROR_TIMEOUT
+ // FINGERPRINT_ERROR_NO_SPACE
+ final int error = arg1;
+ clientData.state = STATE_IDLE;
+ if (clientData.receiver != null) {
+ try {
+ clientData.receiver.onError(error);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "can't send message to client. Did it die?", e);
+ }
+ }
+ }
+ }
+ break;
+ case FingerprintManager.FINGERPRINT_SCANNED: {
+ final int fingerId = arg1;
+ final int confidence = arg2;
+ if (clientData.state == STATE_LISTENING && clientData.receiver != null) {
+ try {
+ clientData.receiver.onScanned(fingerId, confidence);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "can't send message to client. Did it die?", e);
+ }
+ }
+ break;
+ }
+ case FingerprintManager.FINGERPRINT_TEMPLATE_ENROLLING: {
+ if (clientData.state == STATE_ENROLLING) {
+ final int fingerId = arg1;
+ final int remaining = arg2;
+ if (remaining == 0) {
+ FingerprintUtils.addFingerprintIdForUser(fingerId,
+ getContentResolver(), clientData.userId);
+ clientData.state = STATE_IDLE; // Nothing left to do
+ }
+ if (clientData.receiver != null) {
+ try {
+ clientData.receiver.onEnrollResult(fingerId, remaining);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "can't send message to client. Did it die?", e);
+ }
+ }
+ }
+ break;
+ }
+ case FingerprintManager.FINGERPRINT_TEMPLATE_REMOVED: {
+ int fingerId = arg1;
+ if (fingerId == 0) throw new IllegalStateException("Got illegal id from HAL");
+ if (clientData.state == STATE_DELETING) {
+ FingerprintUtils.removeFingerprintIdForUser(fingerId, getContentResolver(),
+ clientData.userId);
+ if (clientData.receiver != null) {
+ try {
+ clientData.receiver.onRemoved(fingerId);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "can't send message to client. Did it die?", e);
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ int enroll(IFingerprintServiceReceiver receiver, long timeout, int userId) {
+ ClientData clientData = mClients.get(receiver);
+ if (clientData != null) {
+ if (clientData.userId != userId) throw new IllegalStateException("Bad user");
+ clientData.state = STATE_ENROLLING;
+ return nativeEnroll((int) (timeout / MS_PER_SEC));
+ }
+ return -1;
+ }
+
+ int remove(IFingerprintServiceReceiver receiver, int fingerId, int userId) {
+ ClientData clientData = mClients.get(receiver);
+ if (clientData != null) {
+ if (clientData.userId != userId) throw new IllegalStateException("Bad user");
+ clientData.state = STATE_DELETING;
+ // The fingerprint id will be removed when we get confirmation from the HAL
+ return nativeRemove(fingerId);
+ }
+ return -1;
+ }
+
+ void startListening(IFingerprintServiceReceiver receiver, int userId) {
+ ClientData clientData = new ClientData();
+ clientData.state = STATE_LISTENING;
+ clientData.receiver = receiver;
+ clientData.userId = userId;
+ mClients.put(receiver, clientData);
+ }
+
+ void stopListening(IFingerprintServiceReceiver receiver, int userId) {
+ ClientData clientData = mClients.get(receiver);
+ if (clientData != null) {
+ clientData.state = STATE_IDLE;
+ clientData.userId = -1;
+ clientData.receiver = null;
+ }
+ mClients.remove(receiver);
+ }
+
+ private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
+ IFingerprintServiceReceiver mReceiver;
+ public int enroll(long timeout, int userId) {
+ return mReceiver != null ? FingerprintService.this.enroll(mReceiver, timeout, userId)
+ : FingerprintManager.FINGERPRINT_ERROR_NO_RECEIVER;
+ }
+
+ public int remove(int fingerprintId, int userId) {
+ return FingerprintService.this.remove(mReceiver, fingerprintId, userId);
+ }
+
+ public void startListening(IFingerprintServiceReceiver receiver, int userId) {
+ mReceiver = receiver;
+ FingerprintService.this.startListening(receiver, userId);
+ }
+
+ public void stopListening(int userId) {
+ FingerprintService.this.stopListening(mReceiver, userId);
+ }
+ }
+}
diff --git a/core/java/android/service/fingerprint/FingerprintUtils.java b/core/java/android/service/fingerprint/FingerprintUtils.java
new file mode 100644
index 0000000..81a2aac
--- /dev/null
+++ b/core/java/android/service/fingerprint/FingerprintUtils.java
@@ -0,0 +1,85 @@
+/**
+ * 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.fingerprint;
+
+import android.content.ContentResolver;
+import android.provider.Settings;
+import android.util.Log;
+
+import java.util.Arrays;
+
+class FingerprintUtils {
+ private static final boolean DEBUG = true;
+ private static final String TAG = "FingerprintUtils";
+
+ public static int[] getFingerprintIdsForUser(ContentResolver res, int userId) {
+ String fingerIdsRaw = Settings.Secure.getStringForUser(res,
+ Settings.Secure.USER_FINGERPRINT_IDS, userId);
+
+ String[] fingerStringIds = fingerIdsRaw.replace("[","").replace("]","").split(", ");
+ int result[] = new int[fingerStringIds.length];
+ for (int i = 0; i < result.length; i++) {
+ try {
+ result[i] = Integer.decode(fingerStringIds[i]);
+ } catch (NumberFormatException e) {
+ if (DEBUG) Log.d(TAG, "Error when parsing finger id " + fingerStringIds[i]);
+ }
+ }
+ return result;
+ }
+
+ public static void addFingerprintIdForUser(int fingerId, ContentResolver res, int userId) {
+ int[] fingerIds = getFingerprintIdsForUser(res, userId);
+
+ // FingerId 0 has special meaning.
+ if (fingerId == 0) return;
+
+ // Don't allow dups
+ for (int i = 0; i < fingerIds.length; i++) {
+ if (fingerIds[i] == fingerId) return;
+ }
+ int[] newList = Arrays.copyOf(fingerIds, fingerIds.length + 1);
+ newList[fingerIds.length] = fingerId;
+ Settings.Secure.putStringForUser(res, Settings.Secure.USER_FINGERPRINT_IDS,
+ Arrays.toString(newList), userId);
+ }
+
+ public static boolean removeFingerprintIdForUser(int fingerId, ContentResolver res, int userId)
+ {
+ // FingerId 0 has special meaning. The HAL layer is supposed to remove each finger one
+ // at a time and invoke notify() for each fingerId. If we get called with 0 here, it means
+ // something bad has happened.
+ if (fingerId == 0) throw new IllegalStateException("Bad fingerId");
+
+ int[] fingerIds = getFingerprintIdsForUser(res, userId);
+ int[] resultIds = Arrays.copyOf(fingerIds, fingerIds.length);
+ int resultCount = 0;
+ for (int i = 0; i < fingerIds.length; i++) {
+ if (fingerId != fingerIds[i]) {
+ resultIds[resultCount++] = fingerIds[i];
+ }
+ }
+ if (resultCount > 0) {
+ Settings.Secure.putStringForUser(res, Settings.Secure.USER_FINGERPRINT_IDS,
+ Arrays.toString(Arrays.copyOf(resultIds, resultCount)), userId);
+ return true;
+ }
+ return false;
+ }
+
+};
+
diff --git a/core/java/android/service/fingerprint/IFingerprintService.aidl b/core/java/android/service/fingerprint/IFingerprintService.aidl
new file mode 100644
index 0000000..e92c20c
--- /dev/null
+++ b/core/java/android/service/fingerprint/IFingerprintService.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.fingerprint;
+
+import android.os.Bundle;
+import android.service.fingerprint.IFingerprintServiceReceiver;
+
+/**
+ * Communication channel from client to the fingerprint service.
+ * @hide
+ */
+interface IFingerprintService {
+ // Returns 0 if successfully started, -1 otherwise
+ int enroll(long timeout, int userId);
+
+ // Returns 0 if fingerprintId's template can be removed, -1 otherwise
+ int remove(int fingerprintId, int userId);
+
+ // Start listening for fingerprint events. This has the side effect of starting
+ // the hardware if not already started.
+ oneway void startListening(IFingerprintServiceReceiver receiver, int userId);
+
+ // Stops listening for fingerprints
+ oneway void stopListening(int userId);
+}
diff --git a/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl b/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl
new file mode 100644
index 0000000..4826b59
--- /dev/null
+++ b/core/java/android/service/fingerprint/IFingerprintServiceReceiver.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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.fingerprint;
+
+import android.os.Bundle;
+import android.os.UserHandle;
+
+/**
+ * Communication channel from the FingerprintService back to FingerprintManager.
+ * @hide
+ */
+oneway interface IFingerprintServiceReceiver {
+ void onEnrollResult(int fingerprintId, int remaining);
+ void onScanned(int fingerprintId, int confidence);
+ void onError(int error);
+ void onRemoved(int fingerprintId);
+}
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 72720d1..e7cdc4e 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -87,7 +87,7 @@
}
private String key() {
- return pkg + '|' + id + '|' + tag + '|' + uid;
+ return user.getIdentifier() + "|" + pkg + "|" + id + "|" + tag + "|" + uid;
}
public void writeToParcel(Parcel out, int flags) {
diff --git a/core/java/android/service/voice/IVoiceInteractionSession.aidl b/core/java/android/service/voice/IVoiceInteractionSession.aidl
index 7dbf66b..9f9c312 100644
--- a/core/java/android/service/voice/IVoiceInteractionSession.aidl
+++ b/core/java/android/service/voice/IVoiceInteractionSession.aidl
@@ -16,13 +16,14 @@
package android.service.voice;
-import android.os.Bundle;
-
-import com.android.internal.app.IVoiceInteractorCallback;
-import com.android.internal.app.IVoiceInteractorRequest;
+import android.content.Intent;
/**
* @hide
*/
-interface IVoiceInteractionSession {
+oneway interface IVoiceInteractionSession {
+ void taskStarted(in Intent intent, int taskId);
+ void taskFinished(in Intent intent, int taskId);
+ void closeSystemDialogs();
+ void destroy();
}
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index d005890..e15489b 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -27,6 +27,19 @@
import android.os.ServiceManager;
import com.android.internal.app.IVoiceInteractionManagerService;
+/**
+ * Top-level service of the current global voice interactor, which is providing
+ * support for hotwording, the back-end of a {@link android.app.VoiceInteractor}, etc.
+ * The current VoiceInteractionService that has been selected by the user is kept
+ * always running by the system, to allow it to do things like listen for hotwords
+ * in the background to instigate voice interactions.
+ *
+ * <p>Because this service is always running, it should be kept as lightweight as
+ * possible. Heavy-weight operations (including showing UI) should be implemented
+ * in the associated {@link android.service.voice.VoiceInteractionSessionService} when
+ * an actual voice interaction is taking place, and that service should run in a
+ * separate process from this one.
+ */
public class VoiceInteractionService extends Service {
/**
* The {@link Intent} that must be declared as handled by the service.
@@ -51,11 +64,9 @@
IVoiceInteractionManagerService mSystemService;
- public void startVoiceActivity(Intent intent, Bundle sessionArgs) {
+ public void startSession(Bundle args) {
try {
- mSystemService.startVoiceActivity(intent,
- intent.resolveType(getContentResolver()),
- mInterface, sessionArgs);
+ mSystemService.startSession(mInterface, args);
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 963b6b4..a83544d 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -16,7 +16,14 @@
package android.service.voice;
+import android.app.Dialog;
+import android.app.Instrumentation;
import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Region;
+import android.inputmethodservice.SoftInputWindow;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -25,16 +32,53 @@
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import com.android.internal.app.IVoiceInteractionManagerService;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.IVoiceInteractorCallback;
import com.android.internal.app.IVoiceInteractorRequest;
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.SomeArgs;
-public abstract class VoiceInteractionSession {
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+
+public abstract class VoiceInteractionSession implements KeyEvent.Callback {
static final String TAG = "VoiceInteractionSession";
static final boolean DEBUG = true;
+ final Context mContext;
+ final HandlerCaller mHandlerCaller;
+
+ final KeyEvent.DispatcherState mDispatcherState = new KeyEvent.DispatcherState();
+
+ IVoiceInteractionManagerService mSystemService;
+ IBinder mToken;
+
+ int mTheme = 0;
+ LayoutInflater mInflater;
+ TypedArray mThemeAttrs;
+ View mRootView;
+ FrameLayout mContentFrame;
+ SoftInputWindow mWindow;
+
+ boolean mInitialized;
+ boolean mWindowAdded;
+ boolean mWindowVisible;
+ boolean mWindowWasVisible;
+ boolean mInShowWindow;
+
+ final ArrayMap<IBinder, Request> mActiveRequests = new ArrayMap<IBinder, Request>();
+
+ final Insets mTmpInsets = new Insets();
+ final int[] mTmpLocation = new int[2];
+
final IVoiceInteractor mInteractor = new IVoiceInteractor.Stub() {
@Override
public IVoiceInteractorRequest startConfirmation(String callingPackage,
@@ -71,6 +115,27 @@
};
final IVoiceInteractionSession mSession = new IVoiceInteractionSession.Stub() {
+ @Override
+ public void taskStarted(Intent intent, int taskId) {
+ mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIO(MSG_TASK_STARTED,
+ taskId, intent));
+ }
+
+ @Override
+ public void taskFinished(Intent intent, int taskId) {
+ mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIO(MSG_TASK_FINISHED,
+ taskId, intent));
+ }
+
+ @Override
+ public void closeSystemDialogs() {
+ mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_CLOSE_SYSTEM_DIALOGS));
+ }
+
+ @Override
+ public void destroy() {
+ mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_DESTROY));
+ }
};
public static class Request {
@@ -129,38 +194,128 @@
static final int MSG_SUPPORTS_COMMANDS = 3;
static final int MSG_CANCEL = 4;
- final Context mContext;
- final HandlerCaller mHandlerCaller;
- final HandlerCaller.Callback mHandlerCallerCallback = new HandlerCaller.Callback() {
+ static final int MSG_TASK_STARTED = 100;
+ static final int MSG_TASK_FINISHED = 101;
+ static final int MSG_CLOSE_SYSTEM_DIALOGS = 102;
+ static final int MSG_DESTROY = 103;
+
+ class MyCallbacks implements HandlerCaller.Callback, SoftInputWindow.Callback {
@Override
public void executeMessage(Message msg) {
- SomeArgs args = (SomeArgs)msg.obj;
+ SomeArgs args;
switch (msg.what) {
case MSG_START_CONFIRMATION:
+ args = (SomeArgs)msg.obj;
if (DEBUG) Log.d(TAG, "onConfirm: req=" + ((Request) args.arg2).mInterface
+ " prompt=" + args.arg3 + " extras=" + args.arg4);
onConfirm((Caller)args.arg1, (Request)args.arg2, (String)args.arg3,
(Bundle)args.arg4);
break;
case MSG_START_COMMAND:
+ args = (SomeArgs)msg.obj;
if (DEBUG) Log.d(TAG, "onCommand: req=" + ((Request) args.arg2).mInterface
+ " command=" + args.arg3 + " extras=" + args.arg4);
onCommand((Caller) args.arg1, (Request) args.arg2, (String) args.arg3,
(Bundle) args.arg4);
break;
case MSG_SUPPORTS_COMMANDS:
+ args = (SomeArgs)msg.obj;
if (DEBUG) Log.d(TAG, "onGetSupportedCommands: cmds=" + args.arg2);
args.arg1 = onGetSupportedCommands((Caller) args.arg1, (String[]) args.arg2);
break;
case MSG_CANCEL:
+ args = (SomeArgs)msg.obj;
if (DEBUG) Log.d(TAG, "onCancel: req=" + ((Request) args.arg1).mInterface);
onCancel((Request)args.arg1);
break;
+ case MSG_TASK_STARTED:
+ if (DEBUG) Log.d(TAG, "onTaskStarted: intent=" + msg.obj
+ + " taskId=" + msg.arg1);
+ onTaskStarted((Intent) msg.obj, msg.arg1);
+ break;
+ case MSG_TASK_FINISHED:
+ if (DEBUG) Log.d(TAG, "onTaskFinished: intent=" + msg.obj
+ + " taskId=" + msg.arg1);
+ onTaskFinished((Intent) msg.obj, msg.arg1);
+ break;
+ case MSG_CLOSE_SYSTEM_DIALOGS:
+ if (DEBUG) Log.d(TAG, "onCloseSystemDialogs");
+ onCloseSystemDialogs();
+ break;
+ case MSG_DESTROY:
+ if (DEBUG) Log.d(TAG, "doDestroy");
+ doDestroy();
+ break;
}
}
- };
- final ArrayMap<IBinder, Request> mActiveRequests = new ArrayMap<IBinder, Request>();
+ @Override
+ public void onBackPressed() {
+ VoiceInteractionSession.this.onBackPressed();
+ }
+ }
+
+ final MyCallbacks mCallbacks = new MyCallbacks();
+
+ /**
+ * Information about where interesting parts of the input method UI appear.
+ */
+ public static final class Insets {
+ /**
+ * This is the top part of the UI that is the main content. It is
+ * used to determine the basic space needed, to resize/pan the
+ * application behind. It is assumed that this inset does not
+ * change very much, since any change will cause a full resize/pan
+ * of the application behind. This value is relative to the top edge
+ * of the input method window.
+ */
+ public int contentTopInsets;
+
+ /**
+ * This is the region of the UI that is touchable. It is used when
+ * {@link #touchableInsets} is set to {@link #TOUCHABLE_INSETS_REGION}.
+ * The region should be specified relative to the origin of the window frame.
+ */
+ public final Region touchableRegion = new Region();
+
+ /**
+ * Option for {@link #touchableInsets}: the entire window frame
+ * can be touched.
+ */
+ public static final int TOUCHABLE_INSETS_FRAME
+ = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
+
+ /**
+ * Option for {@link #touchableInsets}: the area inside of
+ * the content insets can be touched.
+ */
+ public static final int TOUCHABLE_INSETS_CONTENT
+ = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
+
+ /**
+ * Option for {@link #touchableInsets}: the region specified by
+ * {@link #touchableRegion} can be touched.
+ */
+ public static final int TOUCHABLE_INSETS_REGION
+ = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
+
+ /**
+ * Determine which area of the window is touchable by the user. May
+ * be one of: {@link #TOUCHABLE_INSETS_FRAME},
+ * {@link #TOUCHABLE_INSETS_CONTENT}, or {@link #TOUCHABLE_INSETS_REGION}.
+ */
+ public int touchableInsets;
+ }
+
+ final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer =
+ new ViewTreeObserver.OnComputeInternalInsetsListener() {
+ public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
+ onComputeInsets(mTmpInsets);
+ info.contentInsets.top = info.visibleInsets.top = mTmpInsets.contentTopInsets;
+ info.touchableRegion.set(mTmpInsets.touchableRegion);
+ info.setTouchableInsets(mTmpInsets.touchableInsets);
+ }
+ };
public VoiceInteractionSession(Context context) {
this(context, new Handler());
@@ -169,7 +324,7 @@
public VoiceInteractionSession(Context context, Handler handler) {
mContext = context;
mHandlerCaller = new HandlerCaller(context, handler.getLooper(),
- mHandlerCallerCallback, true);
+ mCallbacks, true);
}
Request findRequest(IVoiceInteractorCallback callback, boolean newRequest) {
@@ -188,6 +343,192 @@
}
}
+ void doCreate(IVoiceInteractionManagerService service, IBinder token, Bundle args) {
+ mSystemService = service;
+ mToken = token;
+ onCreate(args);
+ }
+
+ void doDestroy() {
+ if (mInitialized) {
+ mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
+ mInsetsComputer);
+ if (mWindowAdded) {
+ mWindow.dismiss();
+ mWindowAdded = false;
+ }
+ mInitialized = false;
+ }
+ }
+
+ void initViews() {
+ mInitialized = true;
+
+ mThemeAttrs = mContext.obtainStyledAttributes(android.R.styleable.VoiceInteractionSession);
+ mRootView = mInflater.inflate(
+ com.android.internal.R.layout.voice_interaction_session, null);
+ mRootView.setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+ mWindow.setContentView(mRootView);
+ mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
+
+ mContentFrame = (FrameLayout)mRootView.findViewById(android.R.id.content);
+ }
+
+ public void showWindow() {
+ if (DEBUG) Log.v(TAG, "Showing window: mWindowAdded=" + mWindowAdded
+ + " mWindowVisible=" + mWindowVisible);
+
+ if (mInShowWindow) {
+ Log.w(TAG, "Re-entrance in to showWindow");
+ return;
+ }
+
+ try {
+ mInShowWindow = true;
+ if (!mWindowVisible) {
+ mWindowVisible = true;
+ if (!mWindowAdded) {
+ mWindowAdded = true;
+ View v = onCreateContentView();
+ if (v != null) {
+ setContentView(v);
+ }
+ }
+ mWindow.show();
+ }
+ } finally {
+ mWindowWasVisible = true;
+ mInShowWindow = false;
+ }
+ }
+
+ public void hideWindow() {
+ if (mWindowVisible) {
+ mWindow.hide();
+ mWindowVisible = false;
+ }
+ }
+
+ /**
+ * You can call this to customize the theme used by your IME's window.
+ * This must be set before {@link #onCreate}, so you
+ * will typically call it in your constructor with the resource ID
+ * of your custom theme.
+ */
+ public void setTheme(int theme) {
+ if (mWindow != null) {
+ throw new IllegalStateException("Must be called before onCreate()");
+ }
+ mTheme = theme;
+ }
+
+ public void startVoiceActivity(Intent intent) {
+ if (mToken == null) {
+ throw new IllegalStateException("Can't call before onCreate()");
+ }
+ try {
+ int res = mSystemService.startVoiceActivity(mToken, intent,
+ intent.resolveType(mContext.getContentResolver()));
+ Instrumentation.checkStartActivityResult(res, intent);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public LayoutInflater getLayoutInflater() {
+ return mInflater;
+ }
+
+ public Dialog getWindow() {
+ return mWindow;
+ }
+
+ public void finish() {
+ if (mToken == null) {
+ throw new IllegalStateException("Can't call before onCreate()");
+ }
+ hideWindow();
+ try {
+ mSystemService.finish(mToken);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public void onCreate(Bundle args) {
+ mTheme = mTheme != 0 ? mTheme
+ : com.android.internal.R.style.Theme_DeviceDefault_VoiceInteractionSession;
+ mInflater = (LayoutInflater)mContext.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ mWindow = new SoftInputWindow(mContext, "VoiceInteractionSession", mTheme,
+ mCallbacks, this, mDispatcherState, true);
+ mWindow.getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+ initViews();
+ mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT);
+ mWindow.setToken(mToken);
+ }
+
+ public void onDestroy() {
+ }
+
+ public View onCreateContentView() {
+ return null;
+ }
+
+ public void setContentView(View view) {
+ mContentFrame.removeAllViews();
+ mContentFrame.addView(view, new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+
+ }
+
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return false;
+ }
+
+ public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+ return false;
+ }
+
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ return false;
+ }
+
+ public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
+ return false;
+ }
+
+ public void onBackPressed() {
+ finish();
+ }
+
+ public void onCloseSystemDialogs() {
+ finish();
+ }
+
+ /**
+ * Compute the interesting insets into your UI. The default implementation
+ * uses the entire window frame as the insets. The default touchable
+ * insets are {@link Insets#TOUCHABLE_INSETS_FRAME}.
+ *
+ * @param outInsets Fill in with the current UI insets.
+ */
+ public void onComputeInsets(Insets outInsets) {
+ int[] loc = mTmpLocation;
+ View decor = getWindow().getWindow().getDecorView();
+ decor.getLocationInWindow(loc);
+ outInsets.contentTopInsets = loc[1];
+ outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_FRAME;
+ outInsets.touchableRegion.setEmpty();
+ }
+
+ public void onTaskStarted(Intent intent, int taskId) {
+ }
+
+ public void onTaskFinished(Intent intent, int taskId) {
+ finish();
+ }
+
public abstract boolean[] onGetSupportedCommands(Caller caller, String[] commands);
public abstract void onConfirm(Caller caller, Request request, String prompt, Bundle extras);
public abstract void onCommand(Caller caller, Request request, String command, Bundle extras);
diff --git a/core/java/android/service/voice/VoiceInteractionSessionService.java b/core/java/android/service/voice/VoiceInteractionSessionService.java
index 40e5bba..e793849 100644
--- a/core/java/android/service/voice/VoiceInteractionSessionService.java
+++ b/core/java/android/service/voice/VoiceInteractionSessionService.java
@@ -29,11 +29,15 @@
import com.android.internal.os.HandlerCaller;
import com.android.internal.os.SomeArgs;
+/**
+ * An active voice interaction session, initiated by a {@link VoiceInteractionService}.
+ */
public abstract class VoiceInteractionSessionService extends Service {
static final int MSG_NEW_SESSION = 1;
IVoiceInteractionManagerService mSystemService;
+ VoiceInteractionSession mSession;
IVoiceInteractionSessionService mInterface = new IVoiceInteractionSessionService.Stub() {
public void newSession(IBinder token, Bundle args) {
@@ -73,9 +77,14 @@
}
void doNewSession(IBinder token, Bundle args) {
- VoiceInteractionSession session = onNewSession(args);
+ if (mSession != null) {
+ mSession.doDestroy();
+ mSession = null;
+ }
+ mSession = onNewSession(args);
try {
- mSystemService.deliverNewSession(token, session.mSession, session.mInteractor);
+ mSystemService.deliverNewSession(token, mSession.mSession, mSession.mInteractor);
+ mSession.doCreate(mSystemService, token, args);
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/speech/tts/BlockingAudioTrack.java b/core/java/android/speech/tts/BlockingAudioTrack.java
index 186cb49..92bb0ac 100644
--- a/core/java/android/speech/tts/BlockingAudioTrack.java
+++ b/core/java/android/speech/tts/BlockingAudioTrack.java
@@ -83,7 +83,7 @@
mVolume = volume;
mPan = pan;
- mBytesPerFrame = getBytesPerFrame(mAudioFormat) * mChannelCount;
+ mBytesPerFrame = AudioFormat.getBytesPerSample(mAudioFormat) * mChannelCount;
mIsShortUtterance = false;
mAudioBufferSize = 0;
mBytesWritten = 0;
@@ -229,17 +229,6 @@
return audioTrack;
}
- private static int getBytesPerFrame(int audioFormat) {
- if (audioFormat == AudioFormat.ENCODING_PCM_8BIT) {
- return 1;
- } else if (audioFormat == AudioFormat.ENCODING_PCM_16BIT) {
- return 2;
- }
-
- return -1;
- }
-
-
private void blockUntilDone(AudioTrack audioTrack) {
if (mBytesWritten <= 0) {
return;
diff --git a/core/java/android/speech/tts/FileSynthesisCallback.java b/core/java/android/speech/tts/FileSynthesisCallback.java
index 717aeb6..d84f7f0 100644
--- a/core/java/android/speech/tts/FileSynthesisCallback.java
+++ b/core/java/android/speech/tts/FileSynthesisCallback.java
@@ -278,8 +278,7 @@
private ByteBuffer makeWavHeader(int sampleRateInHz, int audioFormat, int channelCount,
int dataLength) {
- // TODO: is AudioFormat.ENCODING_DEFAULT always the same as ENCODING_PCM_16BIT?
- int sampleSizeInBytes = (audioFormat == AudioFormat.ENCODING_PCM_8BIT ? 1 : 2);
+ int sampleSizeInBytes = AudioFormat.getBytesPerSample(audioFormat);
int byteRate = sampleRateInHz * sampleSizeInBytes * channelCount;
short blockAlign = (short) (sampleSizeInBytes * channelCount);
short bitsPerSample = (short) (sampleSizeInBytes * 8);
diff --git a/core/java/android/transition/MoveImage.java b/core/java/android/transition/MoveImage.java
index e4c3939..183cdd2 100644
--- a/core/java/android/transition/MoveImage.java
+++ b/core/java/android/transition/MoveImage.java
@@ -125,7 +125,7 @@
Matrix startMatrix = (Matrix) startValues.values.get(PROPNAME_MATRIX);
Matrix endMatrix = (Matrix) endValues.values.get(PROPNAME_MATRIX);
- if (!startMatrix.equals(endMatrix)) {
+ if (startMatrix != null && !startMatrix.equals(endMatrix)) {
changes.add(PropertyValuesHolder.ofObject(MatrixClippedDrawable.MATRIX_PROPERTY,
new MatrixEvaluator(), startMatrix, endMatrix));
}
@@ -230,7 +230,9 @@
private static void expandClip(Rect bounds, Matrix matrix, Rect clip, Rect otherClip) {
RectF boundsF = new RectF(bounds);
- matrix.mapRect(boundsF);
+ if (matrix != null) {
+ matrix.mapRect(boundsF);
+ }
clip.left = expandMinDimension(boundsF.left, clip.left, otherClip.left);
clip.top = expandMinDimension(boundsF.top, clip.top, otherClip.top);
clip.right = expandMaxDimension(boundsF.right, clip.right, otherClip.right);
@@ -256,10 +258,20 @@
int drawableWidth = drawable.getIntrinsicWidth();
int drawableHeight = drawable.getIntrinsicHeight();
ImageView.ScaleType scaleType = imageView.getScaleType();
- if (drawableWidth <= 0 || drawableHeight <= 0 || scaleType == ImageView.ScaleType.FIT_XY) {
- return null;
+ Matrix matrix;
+ if (drawableWidth <= 0 || drawableHeight <= 0) {
+ matrix = null;
+ } else if (scaleType == ImageView.ScaleType.FIT_XY) {
+ matrix = new Matrix();
+ float scaleX = imageView.getWidth();
+ scaleX /= drawableWidth;
+ float scaleY = imageView.getHeight();
+ scaleY /= drawableHeight;
+ matrix.setScale(scaleX, scaleY);
+ } else {
+ matrix = new Matrix(imageView.getImageMatrix());
}
- return new Matrix(imageView.getImageMatrix());
+ return matrix;
}
private Rect findClip(ImageView imageView) {
diff --git a/core/java/android/util/Range.java b/core/java/android/util/Range.java
new file mode 100644
index 0000000..9a4bd4b
--- /dev/null
+++ b/core/java/android/util/Range.java
@@ -0,0 +1,144 @@
+/*
+ * 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.util;
+
+import static com.android.internal.util.Preconditions.*;
+
+import android.hardware.camera2.impl.HashCodeHelpers;
+
+/**
+ * Immutable class for describing the range of two numeric values.
+ * <p>
+ * A range (or "interval") defines the inclusive boundaries around a contiguous span of
+ * values of some {@link Comparable} type; for example,
+ * "integers from 1 to 100 inclusive."
+ * </p>
+ * <p>
+ * All ranges are bounded, and the left side of the range is always {@code >=}
+ * the right side of the range.
+ * </p>
+ *
+ * <p>Although the implementation itself is immutable, there is no restriction that objects
+ * stored must also be immutable. If mutable objects are stored here, then the range
+ * effectively becomes mutable. </p>
+ */
+public final class Range<T extends Comparable<? super T>> {
+ /**
+ * Create a new immutable range.
+ *
+ * <p>
+ * The endpoints are {@code [lower, upper]}; that
+ * is the range is bounded. {@code lower} must be {@link Comparable#compareTo lesser or equal}
+ * to {@code upper}.
+ * </p>
+ *
+ * @param lower The lower endpoint (inclusive)
+ * @param upper The upper endpoint (inclusive)
+ *
+ * @throws NullPointerException if {@code lower} or {@code upper} is {@code null}
+ */
+ public Range(final T lower, final T upper) {
+ mLower = checkNotNull(lower, "lower must not be null");
+ mUpper = checkNotNull(upper, "upper must not be null");
+
+ if (lower.compareTo(upper) > 0) {
+ throw new IllegalArgumentException("lower must be less than or equal to upper");
+ }
+ }
+
+ /**
+ * Create a new immutable range, with the argument types inferred.
+ *
+ * <p>
+ * The endpoints are {@code [lower, upper]}; that
+ * is the range is bounded. {@code lower} must be {@link Comparable#compareTo lesser or equal}
+ * to {@code upper}.
+ * </p>
+ *
+ * @param lower The lower endpoint (inclusive)
+ * @param upper The upper endpoint (inclusive)
+ *
+ * @throws NullPointerException if {@code lower} or {@code upper} is {@code null}
+ */
+ public static <T extends Comparable<? super T>> Range<T> create(final T lower, final T upper) {
+ return new Range<T>(lower, upper);
+ }
+
+ /**
+ * Get the lower endpoint.
+ *
+ * @return a non-{@code null} {@code T} reference
+ */
+ public T getLower() {
+ return mLower;
+ }
+
+ /**
+ * Get the upper endpoint.
+ *
+ * @return a non-{@code null} {@code T} reference
+ */
+ public T getUpper() {
+ return mUpper;
+ }
+
+ /**
+ * Compare two ranges for equality.
+ *
+ * <p>A range is considered equal if and only if both the lower and upper endpoints
+ * are also equal.</p>
+ *
+ * @return {@code true} if the ranges are equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Range) {
+ @SuppressWarnings("rawtypes")
+ final
+ Range other = (Range) obj;
+ return mLower.equals(other.mLower) && mUpper.equals(other.mUpper);
+ }
+ return false;
+ }
+
+ /**
+ * Return the range as a string representation {@code "[lower, upper]"}.
+ *
+ * @return string representation of the range
+ */
+ @Override
+ public String toString() {
+ return String.format("[%s, %s]", mLower, mUpper);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return HashCodeHelpers.hashCode(mLower, mUpper);
+ }
+
+ private final T mLower;
+ private final T mUpper;
+};
diff --git a/core/java/android/util/Size.java b/core/java/android/util/Size.java
new file mode 100644
index 0000000..ba1a35f
--- /dev/null
+++ b/core/java/android/util/Size.java
@@ -0,0 +1,98 @@
+/*
+ * 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.util;
+
+/**
+ * Immutable class for describing width and height dimensions in pixels.
+ */
+public final class Size {
+ /**
+ * Create a new immutable Size instance.
+ *
+ * @param width The width of the size, in pixels
+ * @param height The height of the size, in pixels
+ */
+ public Size(int width, int height) {
+ mWidth = width;
+ mHeight = height;
+ }
+
+ /**
+ * Get the width of the size (in pixels).
+ * @return width
+ */
+ public int getWidth() {
+ return mWidth;
+ }
+
+ /**
+ * Get the height of the size (in pixels).
+ * @return height
+ */
+ public int getHeight() {
+ return mHeight;
+ }
+
+ /**
+ * Check if this size is equal to another size.
+ * <p>
+ * Two sizes are equal if and only if both their widths and heights are
+ * equal.
+ * </p>
+ * <p>
+ * A size object is never equal to any other type of object.
+ * </p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Size) {
+ Size other = (Size) obj;
+ return mWidth == other.mWidth && mHeight == other.mHeight;
+ }
+ return false;
+ }
+
+ /**
+ * Return the size represented as a string with the format {@code "WxH"}
+ *
+ * @return string representation of the size
+ */
+ @Override
+ public String toString() {
+ return mWidth + "x" + mHeight;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ // assuming most sizes are <2^16, doing a rotate will give us perfect hashing
+ return mHeight ^ ((mWidth << (Integer.SIZE / 2)) | (mWidth >>> (Integer.SIZE / 2)));
+ }
+
+ private final int mWidth;
+ private final int mHeight;
+};
diff --git a/core/java/android/util/SizeF.java b/core/java/android/util/SizeF.java
new file mode 100644
index 0000000..0a8b4ed
--- /dev/null
+++ b/core/java/android/util/SizeF.java
@@ -0,0 +1,108 @@
+/*
+ * 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.util;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Immutable class for describing width and height dimensions in some arbitrary
+ * unit.
+ * <p>
+ * Width and height are finite values stored as a floating point representation.
+ * </p>
+ */
+public final class SizeF {
+ /**
+ * Create a new immutable SizeF instance.
+ *
+ * <p>Both the {@code width} and the {@code height} must be a finite number.
+ * In particular, {@code NaN} and positive/negative infinity are illegal values.</p>
+ *
+ * @param width The width of the size
+ * @param height The height of the size
+ *
+ * @throws IllegalArgumentException
+ * if either {@code width} or {@code height} was not finite.
+ */
+ public SizeF(final float width, final float height) {
+ mWidth = checkArgumentFinite(width, "width");
+ mHeight = checkArgumentFinite(height, "height");
+ }
+
+ /**
+ * Get the width of the size (as an arbitrary unit).
+ * @return width
+ */
+ public float getWidth() {
+ return mWidth;
+ }
+
+ /**
+ * Get the height of the size (as an arbitrary unit).
+ * @return height
+ */
+ public float getHeight() {
+ return mHeight;
+ }
+
+ /**
+ * Check if this size is equal to another size.
+ *
+ * <p>Two sizes are equal if and only if both their widths and heights are the same.</p>
+ *
+ * <p>For this purpose, the width/height float values are considered to be the same if and only
+ * if the method {@link Float#floatToIntBits(float)} returns the identical {@code int} value
+ * when applied to each.</p>
+ *
+ * @return {@code true} if the objects were equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof SizeF) {
+ final SizeF other = (SizeF) obj;
+ return mWidth == other.mWidth && mHeight == other.mHeight;
+ }
+ return false;
+ }
+
+ /**
+ * Return the size represented as a string with the format {@code "WxH"}
+ *
+ * @return string representation of the size
+ */
+ @Override
+ public String toString() {
+ return mWidth + "x" + mHeight;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return Float.floatToIntBits(mWidth) ^ Float.floatToIntBits(mHeight);
+ }
+
+ private final float mWidth;
+ private final float mHeight;
+};
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index f1523ae..0a76075 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -259,6 +259,14 @@
return delayMillis <= frameDelay ? 0 : delayMillis - frameDelay;
}
+ /**
+ * @return The refresh rate as the nanoseconds between frames
+ * @hide
+ */
+ long getFrameIntervalNanos() {
+ return mFrameIntervalNanos;
+ }
+
void dump(String prefix, PrintWriter writer) {
String innerPrefix = prefix + " ";
writer.print(prefix); writer.println("Choreographer:");
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index ba1c4b6..0afbde9 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -96,7 +96,7 @@
return mTheme;
}
- mThemeResource = getResources().selectDefaultTheme(mThemeResource,
+ mThemeResource = Resources.selectDefaultTheme(mThemeResource,
getApplicationInfo().targetSdkVersion);
initializeTheme();
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 34b85d9..11948b2 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -18,6 +18,7 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.CanvasProperty;
import android.graphics.DrawFilter;
import android.graphics.Matrix;
import android.graphics.NinePatch;
@@ -889,6 +890,16 @@
float radius, long paint);
@Override
+ public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
+ CanvasProperty<Float> radius, CanvasProperty<Paint> paint) {
+ nDrawCircle(mRenderer, cx.getNativeContainer(), cy.getNativeContainer(),
+ radius.getNativeContainer(), paint.getNativeContainer());
+ }
+
+ private static native void nDrawCircle(long renderer, long propCx,
+ long propCy, long propRadius, long propPaint);
+
+ @Override
public void drawColor(int color) {
drawColor(color, PorterDuff.Mode.SRC_OVER);
}
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index 2b29e5c..a94ec3a 100644
--- a/core/java/android/view/GLES20RecordingCanvas.java
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.NonNull;
import android.util.Pools.SynchronizedPool;
/**
@@ -32,19 +33,25 @@
private static final SynchronizedPool<GLES20RecordingCanvas> sPool =
new SynchronizedPool<GLES20RecordingCanvas>(POOL_LIMIT);
+ RenderNode mNode;
+
private GLES20RecordingCanvas() {
super(true, true);
}
- static GLES20RecordingCanvas obtain() {
+ static GLES20RecordingCanvas obtain(@NonNull RenderNode node) {
+ if (node == null) throw new IllegalArgumentException("node cannot be null");
+
GLES20RecordingCanvas canvas = sPool.acquire();
if (canvas == null) {
canvas = new GLES20RecordingCanvas();
}
+ canvas.mNode = node;
return canvas;
}
void recycle() {
+ mNode = null;
sPool.release(this);
}
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index 233f846..7ec2cc6 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -18,6 +18,7 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.CanvasProperty;
import android.graphics.Paint;
import android.graphics.Rect;
@@ -189,4 +190,7 @@
* @hide
*/
abstract void clearLayerUpdates();
+
+ public abstract void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
+ CanvasProperty<Float> radius, CanvasProperty<Paint> paint);
}
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 8b80c3e0..0cfde94 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -239,7 +239,7 @@
* @see #isValid()
*/
public HardwareCanvas start(int width, int height) {
- HardwareCanvas canvas = GLES20RecordingCanvas.obtain();
+ HardwareCanvas canvas = GLES20RecordingCanvas.obtain(this);
canvas.setViewport(width, height);
// The dirty rect should always be null for a display list
canvas.onPreDraw(null);
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index b70ae3d..a675821 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -16,6 +16,9 @@
package android.view;
+import android.graphics.Canvas;
+import android.graphics.CanvasProperty;
+import android.graphics.Paint;
import android.util.SparseIntArray;
import java.lang.ref.WeakReference;
@@ -26,18 +29,22 @@
public final class RenderNodeAnimator {
// Keep in sync with enum RenderProperty in Animator.h
- private static final int TRANSLATION_X = 0;
- private static final int TRANSLATION_Y = 1;
- private static final int TRANSLATION_Z = 2;
- private static final int SCALE_X = 3;
- private static final int SCALE_Y = 4;
- private static final int ROTATION = 5;
- private static final int ROTATION_X = 6;
- private static final int ROTATION_Y = 7;
- private static final int X = 8;
- private static final int Y = 9;
- private static final int Z = 10;
- private static final int ALPHA = 11;
+ public static final int TRANSLATION_X = 0;
+ public static final int TRANSLATION_Y = 1;
+ public static final int TRANSLATION_Z = 2;
+ public static final int SCALE_X = 3;
+ public static final int SCALE_Y = 4;
+ public static final int ROTATION = 5;
+ public static final int ROTATION_X = 6;
+ public static final int ROTATION_Y = 7;
+ public static final int X = 8;
+ public static final int Y = 9;
+ public static final int Z = 10;
+ public static final int ALPHA = 11;
+
+ // Keep in sync with enum PaintFields in Animator.h
+ public static final int PAINT_STROKE_WIDTH = 0;
+ public static final int PAINT_ALPHA = 1;
// ViewPropertyAnimator uses a mask for its values, we need to remap them
// to the enum values here. RenderPropertyAnimator can't use the mask values
@@ -59,8 +66,8 @@
}};
// Keep in sync DeltaValueType in Animator.h
- private static final int DELTA_TYPE_ABSOLUTE = 0;
- private static final int DELTA_TYPE_DELTA = 1;
+ public static final int DELTA_TYPE_ABSOLUTE = 0;
+ public static final int DELTA_TYPE_DELTA = 1;
private RenderNode mTarget;
private long mNativePtr;
@@ -74,6 +81,19 @@
property, deltaType, deltaValue);
}
+ public RenderNodeAnimator(CanvasProperty<Float> property, int deltaType, float deltaValue) {
+ mNativePtr = nCreateCanvasPropertyFloatAnimator(
+ new WeakReference<RenderNodeAnimator>(this),
+ property.getNativeContainer(), deltaType, deltaValue);
+ }
+
+ public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField,
+ int deltaType, float deltaValue) {
+ mNativePtr = nCreateCanvasPropertyPaintAnimator(
+ new WeakReference<RenderNodeAnimator>(this),
+ property.getNativeContainer(), paintField, deltaType, deltaValue);
+ }
+
public void start(View target) {
mTarget = target.mRenderNode;
mTarget.addAnimator(this);
@@ -81,6 +101,15 @@
target.invalidateViewProperty(true, false);
}
+ public void start(Canvas canvas) {
+ if (!(canvas instanceof GLES20RecordingCanvas)) {
+ throw new IllegalArgumentException("Not a GLES20RecordingCanvas");
+ }
+ GLES20RecordingCanvas recordingCanvas = (GLES20RecordingCanvas) canvas;
+ mTarget = recordingCanvas.mNode;
+ mTarget.addAnimator(this);
+ }
+
public void cancel() {
mTarget.removeAnimator(this);
}
@@ -117,6 +146,10 @@
private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis,
int property, int deltaValueType, float deltaValue);
+ private static native long nCreateCanvasPropertyFloatAnimator(WeakReference<RenderNodeAnimator> weakThis,
+ long canvasProperty, int deltaValueType, float deltaValue);
+ private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis,
+ long canvasProperty, int paintField, int deltaValueType, float deltaValue);
private static native void nSetDuration(long nativePtr, int duration);
private static native void nUnref(long nativePtr);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 2d55a01..c15ce44 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -74,8 +74,10 @@
IBinder displayToken, int orientation,
int l, int t, int r, int b,
int L, int T, int R, int B);
- private static native boolean nativeGetDisplayInfo(
- IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo);
+ private static native SurfaceControl.PhysicalDisplayInfo[] nativeGetDisplayConfigs(
+ IBinder displayToken);
+ private static native int nativeGetActiveConfig(IBinder displayToken);
+ private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
private static native void nativeBlankDisplay(IBinder displayToken);
private static native void nativeUnblankDisplay(IBinder displayToken);
@@ -499,14 +501,25 @@
nativeBlankDisplay(displayToken);
}
- public static boolean getDisplayInfo(IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo) {
+ public static SurfaceControl.PhysicalDisplayInfo[] getDisplayConfigs(IBinder displayToken) {
if (displayToken == null) {
throw new IllegalArgumentException("displayToken must not be null");
}
- if (outInfo == null) {
- throw new IllegalArgumentException("outInfo must not be null");
+ return nativeGetDisplayConfigs(displayToken);
+ }
+
+ public static int getActiveConfig(IBinder displayToken) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
}
- return nativeGetDisplayInfo(displayToken, outInfo);
+ return nativeGetActiveConfig(displayToken);
+ }
+
+ public static boolean setActiveConfig(IBinder displayToken, int id) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+ return nativeSetActiveConfig(displayToken, id);
}
public static void setDisplayProjection(IBinder displayToken,
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 3cfe5e9..1765c43 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -23,7 +23,6 @@
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
-import android.os.Looper;
import android.util.AttributeSet;
import android.util.Log;
@@ -119,8 +118,6 @@
private boolean mUpdateLayer;
private boolean mUpdateSurface;
- private SurfaceTexture.OnFrameAvailableListener mUpdateListener;
-
private Canvas mCanvas;
private int mSaveCount;
@@ -370,21 +367,7 @@
mSurface.setDefaultBufferSize(getWidth(), getHeight());
nCreateNativeWindow(mSurface);
- mUpdateListener = new SurfaceTexture.OnFrameAvailableListener() {
- @Override
- public void onFrameAvailable(SurfaceTexture surfaceTexture) {
- // Per SurfaceTexture's documentation, the callback may be invoked
- // from an arbitrary thread
- updateLayer();
-
- if (Looper.myLooper() == Looper.getMainLooper()) {
- invalidate();
- } else {
- postInvalidate();
- }
- }
- };
- mSurface.setOnFrameAvailableListener(mUpdateListener);
+ mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler);
if (mListener != null && !mUpdateSurface) {
mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight());
@@ -422,7 +405,7 @@
// To cancel updates, the easiest thing to do is simply to remove the
// updates listener
if (visibility == VISIBLE) {
- mSurface.setOnFrameAvailableListener(mUpdateListener);
+ mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler);
updateLayerAndInvalidate();
} else {
mSurface.setOnFrameAvailableListener(null);
@@ -767,6 +750,15 @@
mListener = listener;
}
+ private final SurfaceTexture.OnFrameAvailableListener mUpdateListener =
+ new SurfaceTexture.OnFrameAvailableListener() {
+ @Override
+ public void onFrameAvailable(SurfaceTexture surfaceTexture) {
+ updateLayer();
+ invalidate();
+ }
+ };
+
/**
* This listener can be used to be notified when the surface texture
* associated with this texture view is available.
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index eaec8ab..0bf99d3 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -19,7 +19,6 @@
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
-import android.os.SystemClock;
import android.os.Trace;
import android.view.Surface.OutOfResourcesException;
import android.view.View.AttachInfo;
@@ -52,16 +51,29 @@
private static final Rect NULL_RECT = new Rect();
+ private static final long NANOS_PER_MS = 1000000;
+
+ // Keep in sync with DrawFrameTask.h SYNC_* flags
+ // Nothing interesting to report
+ private static final int SYNC_OK = 0x0;
+ // Needs a ViewRoot invalidate
+ private static final int SYNC_INVALIDATE_REQUIRED = 0x1;
+
private int mWidth, mHeight;
private long mNativeProxy;
private boolean mInitialized = false;
private RenderNode mRootNode;
+ private Choreographer mChoreographer;
ThreadedRenderer(boolean translucent) {
long rootNodePtr = nCreateRootRenderNode();
mRootNode = RenderNode.adopt(rootNodePtr);
mRootNode.setClipToBounds(false);
mNativeProxy = nCreateProxy(translucent, rootNodePtr);
+
+ // Setup timing
+ mChoreographer = Choreographer.getInstance();
+ nSetFrameInterval(mNativeProxy, mChoreographer.getFrameIntervalNanos());
}
@Override
@@ -158,16 +170,7 @@
@Override
boolean loadSystemProperties() {
- return false;
- }
-
- /**
- * TODO: Remove
- * Temporary hack to allow RenderThreadTest prototype app to trigger
- * replaying a DisplayList after modifying the displaylist properties
- *
- * @hide */
- public void repeatLastDraw() {
+ return nLoadSystemProperties(mNativeProxy);
}
private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks) {
@@ -194,7 +197,8 @@
@Override
void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) {
attachInfo.mIgnoreDirtyState = true;
- attachInfo.mDrawingTime = SystemClock.uptimeMillis();
+ long frameTimeNanos = mChoreographer.getFrameTimeNanos();
+ attachInfo.mDrawingTime = frameTimeNanos / NANOS_PER_MS;
updateRootDisplayList(view, callbacks);
@@ -203,7 +207,11 @@
if (dirty == null) {
dirty = NULL_RECT;
}
- nSyncAndDrawFrame(mNativeProxy, dirty.left, dirty.top, dirty.right, dirty.bottom);
+ int syncResult = nSyncAndDrawFrame(mNativeProxy, frameTimeNanos,
+ dirty.left, dirty.top, dirty.right, dirty.bottom);
+ if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) {
+ attachInfo.mViewRootImpl.invalidate();
+ }
}
@Override
@@ -297,13 +305,16 @@
private static native long nCreateProxy(boolean translucent, long rootRenderNode);
private static native void nDeleteProxy(long nativeProxy);
+ private static native void nSetFrameInterval(long nativeProxy, long frameIntervalNanos);
+ private static native boolean nLoadSystemProperties(long nativeProxy);
+
private static native boolean nInitialize(long nativeProxy, Surface window);
private static native void nUpdateSurface(long nativeProxy, Surface window);
private static native void nPauseSurface(long nativeProxy, Surface window);
private static native void nSetup(long nativeProxy, int width, int height);
private static native void nSetDisplayListData(long nativeProxy, long displayList,
long newData);
- private static native void nSyncAndDrawFrame(long nativeProxy,
+ private static native int nSyncAndDrawFrame(long nativeProxy, long frameTimeNanos,
int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
private static native void nDestroyCanvasAndSurface(long nativeProxy);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6afff4d..69840c4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6147,12 +6147,12 @@
// call into it as a fallback in case we're in a class that overrides it
// and has logic to perform.
if (fitSystemWindows(insets.getSystemWindowInsets())) {
- return insets.cloneWithSystemWindowInsetsConsumed();
+ return insets.consumeSystemWindowInsets();
}
} else {
// We were called from within a direct call to fitSystemWindows.
if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
- return insets.cloneWithSystemWindowInsetsConsumed();
+ return insets.consumeSystemWindowInsets();
}
}
return insets;
@@ -9958,7 +9958,7 @@
* @attr ref android.R.styleable#View_transformPivotX
*/
public void setPivotX(float pivotX) {
- if (mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
+ if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
invalidateViewProperty(true, false);
mRenderNode.setPivotX(pivotX);
invalidateViewProperty(false, true);
@@ -9999,7 +9999,7 @@
* @attr ref android.R.styleable#View_transformPivotY
*/
public void setPivotY(float pivotY) {
- if (mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
+ if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
invalidateViewProperty(true, false);
mRenderNode.setPivotY(pivotY);
invalidateViewProperty(false, true);
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 48a5bd5..4e91ad4 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -234,6 +234,7 @@
private final int mOverscrollDistance;
private final int mOverflingDistance;
private final boolean mFadingMarqueeEnabled;
+ private final long mGlobalActionsKeyTimeout;
private boolean sHasPermanentMenuKey;
private boolean sHasPermanentMenuKeySet;
@@ -261,6 +262,7 @@
mOverscrollDistance = OVERSCROLL_DISTANCE;
mOverflingDistance = OVERFLING_DISTANCE;
mFadingMarqueeEnabled = true;
+ mGlobalActionsKeyTimeout = GLOBAL_ACTIONS_KEY_TIMEOUT;
}
/**
@@ -342,6 +344,8 @@
com.android.internal.R.dimen.config_viewMinFlingVelocity);
mMaximumFlingVelocity = res.getDimensionPixelSize(
com.android.internal.R.dimen.config_viewMaxFlingVelocity);
+ mGlobalActionsKeyTimeout = res.getInteger(
+ com.android.internal.R.integer.config_globalActionsKeyTimeout);
}
/**
@@ -698,12 +702,26 @@
*
* @return how long a user needs to press the relevant key to bring up
* the global actions dialog.
+ * @deprecated This timeout should not be used by applications
*/
+ @Deprecated
public static long getGlobalActionKeyTimeout() {
return GLOBAL_ACTIONS_KEY_TIMEOUT;
}
/**
+ * The amount of time a user needs to press the relevant key to bring up
+ * the global actions dialog.
+ *
+ * @return how long a user needs to press the relevant key to bring up
+ * the global actions dialog.
+ * @hide
+ */
+ public long getDeviceGlobalActionKeyTimeout() {
+ return mGlobalActionsKeyTimeout;
+ }
+
+ /**
* The amount of friction applied to scrolls and flings.
*
* @return A scalar dimensionless value representing the coefficient of
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 9c44bd1..375f5e3 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -147,6 +147,7 @@
private TypedArray mWindowStyle;
private Callback mCallback;
+ private OnWindowDismissedCallback mOnWindowDismissedCallback;
private WindowManager mWindowManager;
private IBinder mAppToken;
private String mAppName;
@@ -405,7 +406,10 @@
* @param mode The mode that was just finished.
*/
public void onActionModeFinished(ActionMode mode);
+ }
+ /** @hide */
+ public interface OnWindowDismissedCallback {
/**
* Called when a window is dismissed. This informs the callback that the
* window is gone, and it should finish itself.
@@ -586,6 +590,18 @@
return mCallback;
}
+ /** @hide */
+ public final void setOnWindowDismissedCallback(OnWindowDismissedCallback dcb) {
+ mOnWindowDismissedCallback = dcb;
+ }
+
+ /** @hide */
+ public final void dispatchOnWindowDismissed() {
+ if (mOnWindowDismissedCallback != null) {
+ mOnWindowDismissedCallback.onWindowDismissed();
+ }
+ }
+
/**
* Take ownership of this window's surface. The window's view hierarchy
* will no longer draw into the surface, though it will otherwise continue
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 2160efe..294f472 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -29,7 +29,7 @@
* @see View.OnApplyWindowInsetsListener
* @see View#onApplyWindowInsets(WindowInsets)
*/
-public class WindowInsets {
+public final class WindowInsets {
private Rect mSystemWindowInsets;
private Rect mWindowDecorInsets;
private Rect mTempRect;
@@ -151,6 +151,7 @@
* This can include action bars, title bars, toolbars, etc.</p>
*
* @return The left window decor inset
+ * @hide pending API
*/
public int getWindowDecorInsetLeft() {
return mWindowDecorInsets.left;
@@ -164,6 +165,7 @@
* This can include action bars, title bars, toolbars, etc.</p>
*
* @return The top window decor inset
+ * @hide pending API
*/
public int getWindowDecorInsetTop() {
return mWindowDecorInsets.top;
@@ -177,6 +179,7 @@
* This can include action bars, title bars, toolbars, etc.</p>
*
* @return The right window decor inset
+ * @hide pending API
*/
public int getWindowDecorInsetRight() {
return mWindowDecorInsets.right;
@@ -190,6 +193,7 @@
* This can include action bars, title bars, toolbars, etc.</p>
*
* @return The bottom window decor inset
+ * @hide pending API
*/
public int getWindowDecorInsetBottom() {
return mWindowDecorInsets.bottom;
@@ -217,6 +221,7 @@
* This can include action bars, title bars, toolbars, etc.</p>
*
* @return true if any of the window decor inset values are nonzero
+ * @hide pending API
*/
public boolean hasWindowDecorInsets() {
return mWindowDecorInsets.left != 0 || mWindowDecorInsets.top != 0 ||
@@ -246,13 +251,28 @@
return mIsRound;
}
- public WindowInsets cloneWithSystemWindowInsetsConsumed() {
+ /**
+ * Returns a copy of this WindowInsets with the system window insets fully consumed.
+ *
+ * @return A modified copy of this WindowInsets
+ */
+ public WindowInsets consumeSystemWindowInsets() {
final WindowInsets result = new WindowInsets(this);
result.mSystemWindowInsets = new Rect(0, 0, 0, 0);
return result;
}
- public WindowInsets cloneWithSystemWindowInsetsConsumed(boolean left, boolean top,
+ /**
+ * Returns a copy of this WindowInsets with selected system window insets fully consumed.
+ *
+ * @param left true to consume the left system window inset
+ * @param top true to consume the top system window inset
+ * @param right true to consume the right system window inset
+ * @param bottom true to consume the bottom system window inset
+ * @return A modified copy of this WindowInsets
+ * @hide pending API
+ */
+ public WindowInsets consumeSystemWindowInsets(boolean left, boolean top,
boolean right, boolean bottom) {
if (left || top || right || bottom) {
final WindowInsets result = new WindowInsets(this);
@@ -265,19 +285,36 @@
return this;
}
- public WindowInsets cloneWithSystemWindowInsets(int left, int top, int right, int bottom) {
+ /**
+ * Returns a copy of this WindowInsets with selected system window insets replaced
+ * with new values.
+ *
+ * @param left New left inset in pixels
+ * @param top New top inset in pixels
+ * @param right New right inset in pixels
+ * @param bottom New bottom inset in pixels
+ * @return A modified copy of this WindowInsets
+ */
+ public WindowInsets replaceSystemWindowInsets(int left, int top,
+ int right, int bottom) {
final WindowInsets result = new WindowInsets(this);
result.mSystemWindowInsets = new Rect(left, top, right, bottom);
return result;
}
- public WindowInsets cloneWithWindowDecorInsetsConsumed() {
+ /**
+ * @hide
+ */
+ public WindowInsets consumeWindowDecorInsets() {
final WindowInsets result = new WindowInsets(this);
result.mWindowDecorInsets.set(0, 0, 0, 0);
return result;
}
- public WindowInsets cloneWithWindowDecorInsetsConsumed(boolean left, boolean top,
+ /**
+ * @hide
+ */
+ public WindowInsets consumeWindowDecorInsets(boolean left, boolean top,
boolean right, boolean bottom) {
if (left || top || right || bottom) {
final WindowInsets result = new WindowInsets(this);
@@ -290,7 +327,10 @@
return this;
}
- public WindowInsets cloneWithWindowDecorInsets(int left, int top, int right, int bottom) {
+ /**
+ * @hide
+ */
+ public WindowInsets replaceWindowDecorInsets(int left, int top, int right, int bottom) {
final WindowInsets result = new WindowInsets(this);
result.mWindowDecorInsets = new Rect(left, top, right, bottom);
return result;
diff --git a/core/java/android/webkit/ClientCertRequest.java b/core/java/android/webkit/ClientCertRequest.java
index 8951786..588b868 100644
--- a/core/java/android/webkit/ClientCertRequest.java
+++ b/core/java/android/webkit/ClientCertRequest.java
@@ -36,8 +36,6 @@
* host/port pair. The user can clear the cached data using
* {@link WebView#clearClientCertPreferences}.
*
- * TODO(sgurun) unhide
- * @hide
*/
public interface ClientCertRequest {
/**
diff --git a/core/java/android/webkit/PermissionRequest.java b/core/java/android/webkit/PermissionRequest.java
index 2f8850b..3e33498 100644
--- a/core/java/android/webkit/PermissionRequest.java
+++ b/core/java/android/webkit/PermissionRequest.java
@@ -19,14 +19,11 @@
import android.net.Uri;
/**
- * This class wraps a permission request, and is used to request permission for
- * the web content to access the resources.
+ * This interface defines a permission request and is used when web content
+ * requests access to protected resources.
*
- * Either {@link #grant(long) grant()} or {@link #deny()} must be called to response the
- * request, otherwise, {@link WebChromeClient#onPermissionRequest(PermissionRequest)} will
- * not be invoked again if there is other permission request in this WebView.
- *
- * @hide
+ * Either {@link #grant(long) grant()} or {@link #deny()} must be called in UI
+ * thread to respond to the request.
*/
public interface PermissionRequest {
/**
@@ -62,8 +59,6 @@
* must be equals or a subset of granted resources.
* This parameter is designed to avoid granting permission by accident
* especially when new resources are requested by web content.
- * Calling grant(getResources()) has security issue, the new permission
- * will be granted without being noticed.
*/
public void grant(long resources);
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 60cba86..d630a9a 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -304,7 +304,6 @@
* If this method isn't overridden, the permission is denied.
*
* @param request the PermissionRequest from current web content.
- * @hide
*/
public void onPermissionRequest(PermissionRequest request) {
request.deny();
@@ -314,8 +313,7 @@
* Notify the host application that the given permission request
* has been canceled. Any related UI should therefore be hidden.
*
- * @param request the PermissionRequest need be canceled.
- * @hide
+ * @param request the PermissionRequest that needs be canceled.
*/
public void onPermissionRequestCanceled(PermissionRequest request) {}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 98ef66e..7c32c5b 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -171,6 +171,38 @@
}
/**
+ * Used with {@link #setMixedContentMode}
+ *
+ * In this mode, the WebView will allow a secure origin to load content from any other origin,
+ * even if that origin is insecure. This is the least secure mode of operation for the WebView,
+ * and where possible apps should not set this mode.
+ */
+ public static final int MIXED_CONTENT_ALWAYS_ALLOW = 0;
+
+ /**
+ * Used with {@link #setMixedContentMode}
+ *
+ * In this mode, the WebView will not allow a secure origin to load content from an insecure
+ * origin. This is the preferred and most secure mode of operation for the WebView and apps are
+ * strongly advised to use this mode.
+ */
+ public static final int MIXED_CONTENT_NEVER_ALLOW = 1;
+
+ /**
+ * Used with {@link #setMixedContentMode}
+ *
+ * In this mode, the WebView will attempt to be compatible with the approach of a modern web
+ * browser with regard to mixed content. Some insecure content may be allowed to be loaded by
+ * a secure origin and other types of content will be blocked. The types of content are allowed
+ * or blocked may change release to release and are not explicitly defined.
+ *
+ * This mode is intended to be used by apps that are not in control of the content that they
+ * render but desire to operate in a reasonably secure environment. For highest security, apps
+ * are recommended to use {@link #MIXED_CONTENT_NEVER_ALLOW}.
+ */
+ public static final int MIXED_CONTENT_COMPATIBILITY_MODE = 2;
+
+ /**
* Hidden constructor to prevent clients from creating a new settings
* instance or deriving the class.
*
@@ -1403,4 +1435,29 @@
public int getCacheMode() {
throw new MustOverrideException();
}
+
+ /**
+ * Configures the WebView's behavior when a secure origin attempts to load a resource from an
+ * insecure origin.
+ *
+ * By default, apps that target {@link android.os.Build.VERSION_CODES#KITKAT} or below default
+ * to {@link #MIXED_CONTENT_ALWAYS_ALLOW}. Apps targeting
+ * {@link android.os.Build.VERSION_CODES#L} default to {@link #MIXED_CONTENT_NEVER_ALLOW}.
+ *
+ * The preferred and most secure mode of operation for the WebView is
+ * {@link #MIXED_CONTENT_NEVER_ALLOW} and use of {@link #MIXED_CONTENT_ALWAYS_ALLOW} is
+ * strongly discouraged.
+ *
+ * @param mode The mixed content mode to use. One of {@link #MIXED_CONTENT_NEVER_ALLOW},
+ * {@link #MIXED_CONTENT_NEVER_ALLOW} or {@link #MIXED_CONTENT_COMPATIBILITY_MODE}.
+ */
+ public abstract void setMixedContentMode(int mode);
+
+ /**
+ * Gets the current behavior of the WebView with regard to loading insecure content from a
+ * secure origin.
+ * @return The current setting, one of {@link #MIXED_CONTENT_NEVER_ALLOW},
+ * {@link #MIXED_CONTENT_NEVER_ALLOW} or {@link #MIXED_CONTENT_COMPATIBILITY_MODE}.
+ */
+ public abstract int getMixedContentMode();
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index efb246a..91ca7b4 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -33,6 +33,7 @@
import android.os.Message;
import android.os.StrictMode;
import android.print.PrintDocumentAdapter;
+import android.security.KeyChain;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
@@ -250,6 +251,15 @@
implements ViewTreeObserver.OnGlobalFocusChangeListener,
ViewGroup.OnHierarchyChangeListener, ViewDebug.HierarchyHandler {
+ /**
+ * Broadcast Action: Indicates the data reduction proxy setting changed.
+ * Sent by the settings app when user changes the data reduction proxy value. This intent will
+ * always stay as a hidden API.
+ * @hide
+ */
+ public static final String DATA_REDUCTION_PROXY_SETTING_CHANGED =
+ "android.webkit.DATA_REDUCTION_PROXY_SETTING_CHANGED";
+
private static final String LOGTAG = "WebView";
// Throwing an exception for incorrect thread usage if the
@@ -1479,18 +1489,16 @@
* Clears the client certificate preferences table stored in response
* to proceeding/cancelling client cert requests. Note that webview
* automatically clears these preferences when it receives a
- * {@link KeyChain.ACTION_STORAGE_CHANGED}
+ * {@link KeyChain#ACTION_STORAGE_CHANGED} intent. The client certificate
+ * preferences are global for all Webviews.
*
- * @param resultCallback A callback to be invoked when client certs are cleared.
- * The embedder can pass null if not interested in the callback.
- *
- * TODO(sgurun) unhide
- * @hide
+ * @param onCleared A runnable to be invoked when client certs are cleared.
+ * The embedder can pass null if not interested in the
+ * callback. The runnable will be called in UI thread.
*/
- public void clearClientCertPreferences(ValueCallback<Void> resultCallback) {
- checkThread();
+ public static void clearClientCertPreferences(Runnable onCleared) {
if (DebugFlags.TRACE_API) Log.d(LOGTAG, "clearClientCertPreferences");
- mProvider.clearClientCertPreferences(resultCallback);
+ getFactory().getStatics().clearClientCertPreferences(onCleared);
}
/**
@@ -1674,13 +1682,15 @@
/**
* Preauthorize the given origin to access resources.
- * This authorization only valid for this WebView instance life cycle and
+ * The authorization only valid for this WebView instance's life cycle and
* will not retained.
*
+ * In the case that an origin has had resources preauthorized, calls to
+ * {@link WebChromeClient#onPermissionRequest(PermissionRequest)} will not be
+ * made for those resources from that origin.
+ *
* @param origin the origin authorized to access resources
* @param resources the resource authorized to be accessed by origin.
- *
- * @hide
*/
public void preauthorizePermission(Uri origin, long resources) {
checkThread();
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 33a6df6..62b80c4a 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -224,8 +224,6 @@
* @param view The WebView that is initiating the callback
* @param request An instance of a {@link ClientCertRequest}
*
- * TODO(sgurun) unhide
- * @hide
*/
public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
request.cancel();
@@ -287,11 +285,12 @@
* from where the event is dispatched. It gives the host application a chance
* to handle the unhandled input events.
*
- * Note that if the event is a {@link MotionEvent}, then it's lifetime is only that of the
- * function call. If the WebViewClient wishes to use the event beyond that, then it <i>must</i>
- * create a copy of the event.
+ * Note that if the event is a {@link android.view.MotionEvent}, then it's lifetime is only
+ * that of the function call. If the WebViewClient wishes to use the event beyond that, then it
+ * <i>must</i> create a copy of the event.
*
- * It is the responsibility of overriders of this method to call {@link onUnhandledKeyEvent}
+ * It is the responsibility of overriders of this method to call
+ * {@link #onUnhandledKeyEvent(WebView, KeyEvent)}
* when appropriate if they wish to continue receiving events through it.
*
* @param view The WebView that is initiating the callback.
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index e391aaf..945e0e3 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -59,6 +59,13 @@
* {@link android.webkit.WebView#setWebContentsDebuggingEnabled(boolean) }
*/
void setWebContentsDebuggingEnabled(boolean enable);
+
+ /**
+ * Implements the API method:
+ * {@link android.webkit.WebView#clearClientCertPreferences(Runnable) }
+ */
+ void clearClientCertPreferences(Runnable onCleared);
+
}
Statics getStatics();
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index efa5497..5081ff5 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -198,8 +198,6 @@
public void clearSslPreferences();
- public void clearClientCertPreferences(ValueCallback<Void> resultCallback);
-
public WebBackForwardList copyBackForwardList();
public void setFindListener(WebView.FindListener listener);
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 0966be3..f4cd5fc 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -611,6 +611,9 @@
final boolean[] mIsScrap = new boolean[1];
+ private final int[] mScrollOffset = new int[2];
+ private final int[] mScrollConsumed = new int[2];
+
// True when the popup should be hidden because of a call to
// dispatchDisplayHint()
private boolean mPopupHidden;
@@ -3264,13 +3267,14 @@
}
}
- private boolean startScrollIfNeeded(int y) {
+ private boolean startScrollIfNeeded(int y, MotionEvent vtev) {
// Check if we have moved far enough that it looks more like a
// scroll than a tap
final int deltaY = y - mMotionY;
final int distance = Math.abs(deltaY);
final boolean overscroll = mScrollY != 0;
- if (overscroll || distance > mTouchSlop) {
+ if ((overscroll || distance > mTouchSlop) &&
+ (getNestedScrollAxes() & SCROLL_AXIS_VERTICAL) == 0) {
createScrollingCache();
if (overscroll) {
mTouchMode = TOUCH_MODE_OVERSCROLL;
@@ -3292,17 +3296,28 @@
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
- scrollIfNeeded(y);
+ scrollIfNeeded(y, vtev);
return true;
}
return false;
}
- private void scrollIfNeeded(int y) {
- final int rawDeltaY = y - mMotionY;
+ private void scrollIfNeeded(int y, MotionEvent vtev) {
+ int rawDeltaY = y - mMotionY;
+ if (dispatchNestedPreScroll(0, rawDeltaY, mScrollConsumed, mScrollOffset)) {
+ rawDeltaY -= mScrollConsumed[1];
+ mMotionCorrection -= mScrollOffset[1];
+ if (mLastY != Integer.MIN_VALUE) {
+ mLastY -= mScrollOffset[1] + mScrollConsumed[1];
+ }
+ if (vtev != null) {
+ vtev.offsetLocation(0, mScrollOffset[1]);
+ }
+ }
final int deltaY = rawDeltaY - mMotionCorrection;
int incrementalDeltaY = mLastY != Integer.MIN_VALUE ? y - mLastY : deltaY;
+ int lastYCorrection = 0;
if (mTouchMode == TOUCH_MODE_SCROLL) {
if (PROFILE_SCROLLING) {
@@ -3361,39 +3376,48 @@
int overscroll = -incrementalDeltaY -
(motionViewRealTop - motionViewPrevTop);
- overScrollBy(0, overscroll, 0, mScrollY, 0, 0,
- 0, mOverscrollDistance, true);
- if (Math.abs(mOverscrollDistance) == Math.abs(mScrollY)) {
- // Don't allow overfling if we're at the edge.
- if (mVelocityTracker != null) {
- mVelocityTracker.clear();
+ if (dispatchNestedScroll(0, overscroll - incrementalDeltaY, 0, overscroll,
+ mScrollOffset)) {
+ mMotionCorrection -= mScrollOffset[1];
+ lastYCorrection -= mScrollOffset[1];
+ if (vtev != null) {
+ vtev.offsetLocation(0, mScrollOffset[1]);
}
- }
+ } else {
+ overScrollBy(0, overscroll, 0, mScrollY, 0, 0,
+ 0, mOverscrollDistance, true);
+ if (Math.abs(mOverscrollDistance) == Math.abs(mScrollY)) {
+ // Don't allow overfling if we're at the edge.
+ if (mVelocityTracker != null) {
+ mVelocityTracker.clear();
+ }
+ }
- final int overscrollMode = getOverScrollMode();
- if (overscrollMode == OVER_SCROLL_ALWAYS ||
- (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
- !contentFits())) {
- mDirection = 0; // Reset when entering overscroll.
- mTouchMode = TOUCH_MODE_OVERSCROLL;
- if (rawDeltaY > 0) {
- mEdgeGlowTop.onPull((float) overscroll / getHeight());
- if (!mEdgeGlowBottom.isFinished()) {
- mEdgeGlowBottom.onRelease();
+ final int overscrollMode = getOverScrollMode();
+ if (overscrollMode == OVER_SCROLL_ALWAYS ||
+ (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
+ !contentFits())) {
+ mDirection = 0; // Reset when entering overscroll.
+ mTouchMode = TOUCH_MODE_OVERSCROLL;
+ if (deltaY > 0) {
+ mEdgeGlowTop.onPull((float) overscroll / getHeight());
+ if (!mEdgeGlowBottom.isFinished()) {
+ mEdgeGlowBottom.onRelease();
+ }
+ invalidate(mEdgeGlowTop.getBounds(false));
+ } else if (deltaY < 0) {
+ mEdgeGlowBottom.onPull((float) overscroll / getHeight());
+ if (!mEdgeGlowTop.isFinished()) {
+ mEdgeGlowTop.onRelease();
+ }
+ invalidate(mEdgeGlowBottom.getBounds(true));
}
- invalidate(mEdgeGlowTop.getBounds(false));
- } else if (rawDeltaY < 0) {
- mEdgeGlowBottom.onPull((float) overscroll / getHeight());
- if (!mEdgeGlowTop.isFinished()) {
- mEdgeGlowTop.onRelease();
- }
- invalidate(mEdgeGlowBottom.getBounds(true));
}
}
}
mMotionY = y;
}
- mLastY = y;
+ mLastY = y + lastYCorrection;
}
} else if (mTouchMode == TOUCH_MODE_OVERSCROLL) {
if (y != mLastY) {
@@ -3517,6 +3541,8 @@
return false;
}
+ startNestedScroll(SCROLL_AXIS_VERTICAL);
+
if (mFastScroll != null) {
boolean intercepted = mFastScroll.onTouchEvent(ev);
if (intercepted) {
@@ -3525,7 +3551,7 @@
}
initVelocityTrackerIfNotExists();
- mVelocityTracker.addMovement(ev);
+ final MotionEvent vtev = MotionEvent.obtain(ev);
final int actionMasked = ev.getActionMasked();
switch (actionMasked) {
@@ -3535,7 +3561,7 @@
}
case MotionEvent.ACTION_MOVE: {
- onTouchMove(ev);
+ onTouchMove(ev, vtev);
break;
}
@@ -3586,6 +3612,10 @@
}
}
+ if (mVelocityTracker != null) {
+ mVelocityTracker.addMovement(vtev);
+ }
+ vtev.recycle();
return true;
}
@@ -3652,7 +3682,7 @@
}
}
- private void onTouchMove(MotionEvent ev) {
+ private void onTouchMove(MotionEvent ev, MotionEvent vtev) {
int pointerIndex = ev.findPointerIndex(mActivePointerId);
if (pointerIndex == -1) {
pointerIndex = 0;
@@ -3673,7 +3703,7 @@
case TOUCH_MODE_DONE_WAITING:
// Check if we have moved far enough that it looks more like a
// scroll than a tap. If so, we'll enter scrolling mode.
- if (startScrollIfNeeded(y)) {
+ if (startScrollIfNeeded(y, vtev)) {
break;
}
// Otherwise, check containment within list bounds. If we're
@@ -3693,7 +3723,7 @@
break;
case TOUCH_MODE_SCROLL:
case TOUCH_MODE_OVERSCROLL:
- scrollIfNeeded(y);
+ scrollIfNeeded(y, vtev);
break;
}
}
@@ -3935,6 +3965,49 @@
}
@Override
+ public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
+ return ((nestedScrollAxes & SCROLL_AXIS_VERTICAL) != 0);
+ }
+
+ @Override
+ public void onNestedScrollAccepted(View child, View target, int axes) {
+ super.onNestedScrollAccepted(child, target, axes);
+ startNestedScroll(SCROLL_AXIS_VERTICAL);
+ }
+
+ @Override
+ public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
+ int dxUnconsumed, int dyUnconsumed) {
+ final int motionIndex = getChildCount() / 2;
+ final View motionView = getChildAt(motionIndex);
+ final int oldTop = motionView != null ? motionView.getTop() : 0;
+ if (motionView == null || trackMotionScroll(-dyUnconsumed, -dyUnconsumed)) {
+ int myUnconsumed = dyUnconsumed;
+ int myConsumed = 0;
+ if (motionView != null) {
+ myConsumed = motionView.getTop() - oldTop;
+ myUnconsumed -= myConsumed;
+ }
+ dispatchNestedScroll(0, myConsumed, 0, myUnconsumed, null);
+ }
+ }
+
+ @Override
+ public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
+ final int childCount = getChildCount();
+ if (!consumed && childCount > 0 && canScrollList((int) velocityY) &&
+ Math.abs(velocityY) > mMinimumVelocity) {
+ reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
+ if (mFlingRunnable == null) {
+ mFlingRunnable = new FlingRunnable();
+ }
+ mFlingRunnable.start((int) velocityY);
+ return true;
+ }
+ return dispatchNestedFling(velocityX, velocityY, consumed);
+ }
+
+ @Override
public void draw(Canvas canvas) {
super.draw(canvas);
if (mEdgeGlowTop != null) {
@@ -4070,6 +4143,7 @@
mLastY = Integer.MIN_VALUE;
initOrResetVelocityTracker();
mVelocityTracker.addMovement(ev);
+ startNestedScroll(SCROLL_AXIS_VERTICAL);
if (touchMode == TOUCH_MODE_FLING) {
return true;
}
@@ -4087,7 +4161,7 @@
final int y = (int) ev.getY(pointerIndex);
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
- if (startScrollIfNeeded(y)) {
+ if (startScrollIfNeeded(y, null)) {
return true;
}
break;
@@ -4101,6 +4175,7 @@
mActivePointerId = INVALID_POINTER;
recycleVelocityTracker();
reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
+ stopNestedScroll();
break;
}
diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java
index e4575e5..51759c5 100644
--- a/core/java/android/widget/ActionMenuPresenter.java
+++ b/core/java/android/widget/ActionMenuPresenter.java
@@ -649,7 +649,8 @@
private class OverflowPopup extends MenuPopupHelper {
public OverflowPopup(Context context, MenuBuilder menu, View anchorView,
boolean overflowOnly) {
- super(context, menu, anchorView, overflowOnly);
+ super(context, menu, anchorView, overflowOnly,
+ com.android.internal.R.attr.actionOverflowMenuStyle);
setGravity(Gravity.END);
setCallback(mPopupPresenterCallback);
}
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 10ec105..f91865b 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -622,8 +622,8 @@
// only set this if the dropdown is not always visible
mPopup.setOutsideTouchable(!mForceIgnoreOutsideTouch && !mDropDownAlwaysVisible);
mPopup.setTouchInterceptor(mTouchInterceptor);
- mPopup.showAsDropDown(getAnchorView(),
- mDropDownHorizontalOffset, mDropDownVerticalOffset, mDropDownGravity);
+ mPopup.showAsDropDown(getAnchorView(), mDropDownHorizontalOffset,
+ mDropDownVerticalOffset, mDropDownGravity);
mDropDownList.setSelection(ListView.INVALID_POSITION);
if (!mModal || mDropDownList.isInTouchMode()) {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 6e71a5c..01632ae 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -18,6 +18,7 @@
import com.android.internal.R;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -116,6 +117,10 @@
private Drawable mAboveAnchorBackgroundDrawable;
private Drawable mBelowAnchorBackgroundDrawable;
+ // Temporary animation centers. Should be moved into window params?
+ private int mAnchorRelativeX;
+ private int mAnchorRelativeY;
+
private boolean mAboveAnchor;
private int mWindowLayoutType = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
@@ -129,12 +134,14 @@
};
private WeakReference<View> mAnchor;
- private OnScrollChangedListener mOnScrollChangedListener =
+
+ private final OnScrollChangedListener mOnScrollChangedListener =
new OnScrollChangedListener() {
+ @Override
public void onScrollChanged() {
- View anchor = mAnchor != null ? mAnchor.get() : null;
+ final View anchor = mAnchor != null ? mAnchor.get() : null;
if (anchor != null && mPopupView != null) {
- WindowManager.LayoutParams p = (WindowManager.LayoutParams)
+ final WindowManager.LayoutParams p = (WindowManager.LayoutParams)
mPopupView.getLayoutParams();
updateAboveAnchor(findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff,
@@ -143,7 +150,9 @@
}
}
};
+
private int mAnchorXoff, mAnchorYoff, mAnchoredGravity;
+ private boolean mOverlapAnchor;
private boolean mPopupViewInitialLayoutDirectionInherited;
@@ -187,6 +196,7 @@
attrs, com.android.internal.R.styleable.PopupWindow, defStyleAttr, defStyleRes);
mBackground = a.getDrawable(R.styleable.PopupWindow_popupBackground);
+ mOverlapAnchor = a.getBoolean(R.styleable.PopupWindow_overlapAnchor, false);
final int animStyle = a.getResourceId(R.styleable.PopupWindow_popupAnimationStyle, -1);
mAnimationStyle = animStyle == com.android.internal.R.style.Animation_PopupWindow ? -1 :
@@ -934,9 +944,9 @@
// do the job.
if (mAboveAnchorBackgroundDrawable != null) {
if (mAboveAnchor) {
- mPopupView.setBackgroundDrawable(mAboveAnchorBackgroundDrawable);
+ mPopupView.setBackground(mAboveAnchorBackgroundDrawable);
} else {
- mPopupView.setBackgroundDrawable(mBelowAnchorBackgroundDrawable);
+ mPopupView.setBackground(mBelowAnchorBackgroundDrawable);
}
} else {
mPopupView.refreshDrawableState();
@@ -1114,36 +1124,43 @@
}
return mAnimationStyle;
}
-
+
/**
- * <p>Positions the popup window on screen. When the popup window is too
- * tall to fit under the anchor, a parent scroll view is seeked and scrolled
- * up to reclaim space. If scrolling is not possible or not enough, the
- * popup window gets moved on top of the anchor.</p>
- *
- * <p>The height must have been set on the layout parameters prior to
- * calling this method.</p>
- *
+ * Positions the popup window on screen. When the popup window is too tall
+ * to fit under the anchor, a parent scroll view is seeked and scrolled up
+ * to reclaim space. If scrolling is not possible or not enough, the popup
+ * window gets moved on top of the anchor.
+ * <p>
+ * The height must have been set on the layout parameters prior to calling
+ * this method.
+ *
* @param anchor the view on which the popup window must be anchored
* @param p the layout parameters used to display the drop down
- *
+ * @param xoff horizontal offset used to adjust for background padding
+ * @param yoff vertical offset used to adjust for background padding
+ * @param gravity horizontal gravity specifying popup alignment
* @return true if the popup is translated upwards to fit on screen
*/
- private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p,
- int xoff, int yoff, int gravity) {
-
+ private boolean findDropDownPosition(View anchor, WindowManager.LayoutParams p, int xoff,
+ int yoff, int gravity) {
final int anchorHeight = anchor.getHeight();
+ final int anchorWidth = anchor.getWidth();
+ if (mOverlapAnchor) {
+ yoff -= anchorHeight;
+ }
+
anchor.getLocationInWindow(mDrawingLocation);
p.x = mDrawingLocation[0] + xoff;
p.y = mDrawingLocation[1] + anchorHeight + yoff;
- final int hgrav = Gravity.getAbsoluteGravity(gravity, anchor.getLayoutDirection()) &
- Gravity.HORIZONTAL_GRAVITY_MASK;
+ final int hgrav = Gravity.getAbsoluteGravity(gravity, anchor.getLayoutDirection())
+ & Gravity.HORIZONTAL_GRAVITY_MASK;
if (hgrav == Gravity.RIGHT) {
- // Flip the location to align the right sides of the popup and anchor instead of left
- p.x -= mPopupWidth - anchor.getWidth();
+ // Flip the location to align the right sides of the popup and
+ // anchor instead of left.
+ p.x -= mPopupWidth - anchorWidth;
}
-
+
boolean onTop = false;
p.gravity = Gravity.LEFT | Gravity.TOP;
@@ -1152,60 +1169,58 @@
final Rect displayFrame = new Rect();
anchor.getWindowVisibleDisplayFrame(displayFrame);
- int screenY = mScreenLocation[1] + anchorHeight + yoff;
-
+ final int screenY = mScreenLocation[1] + anchorHeight + yoff;
final View root = anchor.getRootView();
- if (screenY + mPopupHeight > displayFrame.bottom ||
- p.x + mPopupWidth - root.getWidth() > 0) {
- // if the drop down disappears at the bottom of the screen. we try to
- // scroll a parent scrollview or move the drop down back up on top of
- // the edit box
+ if (screenY + mPopupHeight > displayFrame.bottom
+ || p.x + mPopupWidth - root.getWidth() > 0) {
+ // If the drop down disappears at the bottom of the screen, we try
+ // to scroll a parent scrollview or move the drop down back up on
+ // top of the edit box.
if (mAllowScrollingAnchorParent) {
- int scrollX = anchor.getScrollX();
- int scrollY = anchor.getScrollY();
- Rect r = new Rect(scrollX, scrollY, scrollX + mPopupWidth + xoff,
- scrollY + mPopupHeight + anchor.getHeight() + yoff);
+ final int scrollX = anchor.getScrollX();
+ final int scrollY = anchor.getScrollY();
+ final Rect r = new Rect(scrollX, scrollY, scrollX + mPopupWidth + xoff,
+ scrollY + mPopupHeight + anchorHeight + yoff);
anchor.requestRectangleOnScreen(r, true);
}
- // now we re-evaluate the space available, and decide from that
+ // Now we re-evaluate the space available, and decide from that
// whether the pop-up will go above or below the anchor.
anchor.getLocationInWindow(mDrawingLocation);
p.x = mDrawingLocation[0] + xoff;
- p.y = mDrawingLocation[1] + anchor.getHeight() + yoff;
+ p.y = mDrawingLocation[1] + anchorHeight + yoff;
- // Preserve the gravity adjustment
+ // Preserve the gravity adjustment.
if (hgrav == Gravity.RIGHT) {
- p.x -= mPopupWidth - anchor.getWidth();
+ p.x -= mPopupWidth - anchorWidth;
}
-
- // determine whether there is more space above or below the anchor
+
+ // Determine whether there is more space above or below the anchor.
anchor.getLocationOnScreen(mScreenLocation);
-
- onTop = (displayFrame.bottom - mScreenLocation[1] - anchor.getHeight() - yoff) <
+ onTop = (displayFrame.bottom - mScreenLocation[1] - anchorHeight - yoff) <
(mScreenLocation[1] - yoff - displayFrame.top);
if (onTop) {
p.gravity = Gravity.LEFT | Gravity.BOTTOM;
p.y = root.getHeight() - mDrawingLocation[1] + yoff;
} else {
- p.y = mDrawingLocation[1] + anchor.getHeight() + yoff;
+ p.y = mDrawingLocation[1] + anchorHeight + yoff;
}
}
if (mClipToScreen) {
final int displayFrameWidth = displayFrame.right - displayFrame.left;
-
- int right = p.x + p.width;
+ final int right = p.x + p.width;
if (right > displayFrameWidth) {
p.x -= right - displayFrameWidth;
}
+
if (p.x < displayFrame.left) {
p.x = displayFrame.left;
p.width = Math.min(p.width, displayFrameWidth);
}
if (onTop) {
- int popupTop = mScreenLocation[1] + yoff - mPopupHeight;
+ final int popupTop = mScreenLocation[1] + yoff - mPopupHeight;
if (popupTop < 0) {
p.y += popupTop;
}
@@ -1215,7 +1230,11 @@
}
p.gravity |= Gravity.DISPLAY_CLIP_VERTICAL;
-
+
+ // Compute the position of the anchor relative to the popup.
+ mAnchorRelativeX = mDrawingLocation[0] - p.x + anchorHeight / 2;
+ mAnchorRelativeY = mDrawingLocation[1] - p.y + anchorWidth / 2;
+
return onTop;
}
@@ -1503,7 +1522,8 @@
}
WeakReference<View> oldAnchor = mAnchor;
- final boolean needsUpdate = updateLocation && (mAnchorXoff != xoff || mAnchorYoff != yoff);
+ final boolean needsUpdate = updateLocation
+ && (mAnchorXoff != xoff || mAnchorYoff != yoff);
if (oldAnchor == null || oldAnchor.get() != anchor || (needsUpdate && !mIsDropdown)) {
registerForScrollChanged(anchor, xoff, yoff, gravity);
} else if (needsUpdate) {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 3e46f68..0fa75a6 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -583,7 +583,8 @@
@Override
public boolean onTouchEvent(MotionEvent ev) {
initVelocityTrackerIfNotExists();
- mVelocityTracker.addMovement(ev);
+
+ MotionEvent vtev = MotionEvent.obtain(ev);
final int action = ev.getAction();
@@ -627,7 +628,8 @@
final int y = (int) ev.getY(activePointerIndex);
int deltaY = mLastMotionY - y;
if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
- deltaY -= mScrollConsumed[1] + mScrollOffset[1];
+ deltaY -= mScrollConsumed[1];
+ vtev.offsetLocation(0, mScrollOffset[1]);
}
if (!mIsBeingDragged && Math.abs(deltaY) > mTouchSlop) {
final ViewParent parent = getParent();
@@ -643,7 +645,7 @@
}
if (mIsBeingDragged) {
// Scroll to follow the motion event
- mLastMotionY = y;
+ mLastMotionY = y - mScrollOffset[1];
final int oldY = mScrollY;
final int range = getScrollRange();
@@ -663,6 +665,7 @@
final int unconsumedY = deltaY - scrolledDeltaY;
if (dispatchNestedScroll(0, scrolledDeltaY, 0, unconsumedY, mScrollOffset)) {
mLastMotionY -= mScrollOffset[1];
+ vtev.offsetLocation(0, mScrollOffset[1]);
} else if (canOverscroll) {
final int pulledToY = oldY + deltaY;
if (pulledToY < 0) {
@@ -720,6 +723,11 @@
mLastMotionY = (int) ev.getY(ev.findPointerIndex(mActivePointerId));
break;
}
+
+ if (mVelocityTracker != null) {
+ mVelocityTracker.addMovement(vtev);
+ }
+ vtev.recycle();
return true;
}
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 1bb577b..04547495 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -59,11 +59,10 @@
void noteVibratorOff(int uid);
void noteStartGps(int uid);
void noteStopGps(int uid);
- void noteScreenOn();
+ void noteScreenState(int state);
void noteScreenBrightness(int brightness);
- void noteScreenOff();
- void noteInputEvent();
void noteUserActivity(int uid, int event);
+ void noteInteractive(boolean interactive);
void noteMobileRadioPowerState(int powerState, long timestampNs);
void notePhoneOn();
void notePhoneOff();
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index 3219ddd..98e35dd 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -24,8 +24,9 @@
import android.service.voice.IVoiceInteractionSession;
interface IVoiceInteractionManagerService {
- void startVoiceActivity(in Intent intent, String resolvedType, IVoiceInteractionService service,
- in Bundle sessionArgs);
- int deliverNewSession(IBinder token, IVoiceInteractionSession session,
+ void startSession(IVoiceInteractionService service, in Bundle sessionArgs);
+ boolean deliverNewSession(IBinder token, IVoiceInteractionSession session,
IVoiceInteractor interactor);
+ int startVoiceActivity(IBinder token, in Intent intent, String resolvedType);
+ void finish(IBinder token);
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
index cba09d1..e3f21cf 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -227,25 +227,39 @@
if (imList.size() <= 1) {
return null;
}
+ // Here we have two rotation groups, depending on the returned boolean value of
+ // {@link InputMethodInfo#supportsSwitchingToNextInputMethod()}.
+ final boolean expectedValueOfSupportsSwitchingToNextInputMethod =
+ imi.supportsSwitchingToNextInputMethod();
final int N = imList.size();
final int currentSubtypeId =
subtype != null ? InputMethodUtils.getSubtypeIdFromHashCode(imi,
subtype.hashCode()) : NOT_A_SUBTYPE_ID;
for (int i = 0; i < N; ++i) {
final ImeSubtypeListItem isli = imList.get(i);
- if (isli.mImi.equals(imi) && isli.mSubtypeId == currentSubtypeId) {
- if (!onlyCurrentIme) {
- return imList.get((i + 1) % N);
- }
- for (int j = 0; j < N - 1; ++j) {
- final ImeSubtypeListItem candidate = imList.get((i + j + 1) % N);
- if (candidate.mImi.equals(imi)) {
- return candidate;
- }
- }
- return null;
+ // Skip until the current IME/subtype is found.
+ if (!isli.mImi.equals(imi) || isli.mSubtypeId != currentSubtypeId) {
+ continue;
}
+ // Found the current IME/subtype. Start searching the next IME/subtype from here.
+ for (int j = 0; j < N - 1; ++j) {
+ final ImeSubtypeListItem candidate = imList.get((i + j + 1) % N);
+ // Skip if the candidate doesn't belong to the expected rotation group.
+ if (expectedValueOfSupportsSwitchingToNextInputMethod !=
+ candidate.mImi.supportsSwitchingToNextInputMethod()) {
+ continue;
+ }
+ // Skip if searching inside the current IME only, but the candidate is not
+ // the current IME.
+ if (onlyCurrentIme && !candidate.mImi.equals(imi)) {
+ continue;
+ }
+ return candidate;
+ }
+ // No appropriate IME/subtype is found in the list. Give up.
+ return null;
}
+ // The current IME/subtype is not found in the list. Give up.
return null;
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index f63fa8a..1aff190 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -51,6 +51,7 @@
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.TimeUtils;
+import android.view.Display;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.net.NetworkStatsFactory;
@@ -88,7 +89,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 104 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 105 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -237,13 +238,14 @@
int mWakeLockNesting;
boolean mWakeLockImportant;
- boolean mScreenOn;
+ int mScreenState = Display.STATE_UNKNOWN;
StopwatchTimer mScreenOnTimer;
int mScreenBrightnessBin = -1;
final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
- Counter mInputEventCounter;
+ boolean mInteractive;
+ StopwatchTimer mInteractiveTimer;
boolean mPhoneOn;
StopwatchTimer mPhoneOnTimer;
@@ -2661,58 +2663,61 @@
getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
}
- public void noteScreenOnLocked() {
- if (!mScreenOn) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
- mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mScreenOn = true;
- mScreenOnTimer.startRunningLocked(elapsedRealtime);
- if (mScreenBrightnessBin >= 0) {
- mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
- }
+ public void noteScreenStateLocked(int state) {
+ if (mScreenState != state) {
+ final int oldState = mScreenState;
+ mScreenState = state;
+ if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState)
+ + ", newState=" + Display.stateToString(state));
- updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), false,
- SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
+ if (state == Display.STATE_ON) {
+ // Screen turning on.
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtime, uptime);
+ mScreenOnTimer.startRunningLocked(elapsedRealtime);
+ if (mScreenBrightnessBin >= 0) {
+ mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime);
+ }
- // Fake a wake lock, so we consider the device waked as long
- // as the screen is on.
- noteStartWakeLocked(-1, -1, "screen", null, WAKE_TYPE_PARTIAL, false,
- elapsedRealtime, uptime);
+ updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), false,
+ SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
- // Update discharge amounts.
- if (mOnBatteryInternal) {
- updateDischargeScreenLevelsLocked(false, true);
- }
- }
- }
+ // Fake a wake lock, so we consider the device waked as long
+ // as the screen is on.
+ noteStartWakeLocked(-1, -1, "screen", null, WAKE_TYPE_PARTIAL, false,
+ elapsedRealtime, uptime);
- public void noteScreenOffLocked() {
- if (mScreenOn) {
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
- mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
- if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
- + Integer.toHexString(mHistoryCur.states));
- addHistoryRecordLocked(elapsedRealtime, uptime);
- mScreenOn = false;
- mScreenOnTimer.stopRunningLocked(elapsedRealtime);
- if (mScreenBrightnessBin >= 0) {
- mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
- }
+ // Update discharge amounts.
+ if (mOnBatteryInternal) {
+ updateDischargeScreenLevelsLocked(false, true);
+ }
+ } else if (oldState == Display.STATE_ON) {
+ // Screen turning off or dozing.
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
+ mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
+ if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: "
+ + Integer.toHexString(mHistoryCur.states));
+ addHistoryRecordLocked(elapsedRealtime, uptime);
+ mScreenOnTimer.stopRunningLocked(elapsedRealtime);
+ if (mScreenBrightnessBin >= 0) {
+ mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
+ }
- noteStopWakeLocked(-1, -1, "screen", WAKE_TYPE_PARTIAL,
- elapsedRealtime, uptime);
+ noteStopWakeLocked(-1, -1, "screen", WAKE_TYPE_PARTIAL,
+ elapsedRealtime, uptime);
- updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), true,
- SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
+ updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), true,
+ SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
- // Update discharge amounts.
- if (mOnBatteryInternal) {
- updateDischargeScreenLevelsLocked(true, false);
+ // Update discharge amounts.
+ if (mOnBatteryInternal) {
+ updateDischargeScreenLevelsLocked(true, false);
+ }
}
}
}
@@ -2730,7 +2735,7 @@
if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: "
+ Integer.toHexString(mHistoryCur.states));
addHistoryRecordLocked(elapsedRealtime, uptime);
- if (mScreenOn) {
+ if (mScreenState == Display.STATE_ON) {
if (mScreenBrightnessBin >= 0) {
mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
}
@@ -2740,10 +2745,6 @@
}
}
- public void noteInputEventAtomic() {
- mInputEventCounter.stepAtomic();
- }
-
public void noteUserActivityLocked(int uid, int event) {
if (mOnBatteryInternal) {
uid = mapUid(uid);
@@ -2751,6 +2752,19 @@
}
}
+ public void noteInteractiveLocked(boolean interactive) {
+ if (mInteractive != interactive) {
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ mInteractive = interactive;
+ if (DEBUG) Slog.v(TAG, "Interactive: " + interactive);
+ if (interactive) {
+ mInteractiveTimer.startRunningLocked(elapsedRealtime);
+ } else {
+ mInteractiveTimer.stopRunningLocked(elapsedRealtime);
+ }
+ }
+ }
+
public void noteMobileRadioPowerState(int powerState, long timestampNs) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
@@ -3449,8 +3463,8 @@
elapsedRealtimeUs, which);
}
- @Override public int getInputEventCount(int which) {
- return mInputEventCounter.getCountLocked(which);
+ @Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
+ return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
}
@Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
@@ -5499,7 +5513,6 @@
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase);
}
- mInputEventCounter = new Counter(mOnBatteryTimeBase);
mPhoneOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase);
for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null,
@@ -5530,6 +5543,7 @@
}
mAudioOnTimer = new StopwatchTimer(null, -6, null, mOnBatteryTimeBase);
mVideoOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
+ mInteractiveTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase);
mOnBattery = mOnBatteryInternal = false;
long uptime = SystemClock.uptimeMillis() * 1000;
long realtime = SystemClock.elapsedRealtime() * 1000;
@@ -5713,7 +5727,7 @@
}
public boolean isScreenOn() {
- return mScreenOn;
+ return mScreenState == Display.STATE_ON;
}
void initTimes(long uptime, long realtime) {
@@ -5753,7 +5767,7 @@
mOnBatteryTimeBase.reset(uptime, realtime);
mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
- if (mScreenOn) {
+ if (mScreenState == Display.STATE_ON) {
mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel;
mDischargeScreenOffUnplugLevel = 0;
} else {
@@ -5773,7 +5787,7 @@
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
mScreenBrightnessTimer[i].reset(false);
}
- mInputEventCounter.reset(false);
+ mInteractiveTimer.reset(false);
mPhoneOnTimer.reset(false);
mAudioOnTimer.reset(false);
mVideoOnTimer.reset(false);
@@ -5874,7 +5888,8 @@
updateKernelWakelocksLocked();
updateNetworkActivityLocked(NET_UPDATE_ALL, SystemClock.elapsedRealtime());
if (mOnBatteryInternal) {
- updateDischargeScreenLevelsLocked(mScreenOn, mScreenOn);
+ final boolean screenOn = mScreenState == Display.STATE_ON;
+ updateDischargeScreenLevelsLocked(screenOn, screenOn);
}
}
@@ -5888,6 +5903,7 @@
final long uptime = mSecUptime * 1000;
final long realtime = mSecRealtime * 1000;
+ final boolean screenOn = mScreenState == Display.STATE_ON;
if (onBattery) {
// We will reset our status if we are unplugging after the
// battery was last full, or the level is at 100, or
@@ -5916,7 +5932,7 @@
}
addHistoryRecordLocked(mSecRealtime, mSecUptime);
mDischargeCurrentLevel = mDischargeUnplugLevel = level;
- if (mScreenOn) {
+ if (screenOn) {
mDischargeScreenOnUnplugLevel = level;
mDischargeScreenOffUnplugLevel = 0;
} else {
@@ -5925,7 +5941,7 @@
}
mDischargeAmountScreenOn = 0;
mDischargeAmountScreenOff = 0;
- updateTimeBasesLocked(true, !mScreenOn, uptime, realtime);
+ updateTimeBasesLocked(true, !screenOn, uptime, realtime);
} else {
pullPendingStateUpdatesLocked();
mHistoryCur.batteryLevel = (byte)level;
@@ -5938,8 +5954,8 @@
mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
}
- updateDischargeScreenLevelsLocked(mScreenOn, mScreenOn);
- updateTimeBasesLocked(false, !mScreenOn, uptime, realtime);
+ updateDischargeScreenLevelsLocked(screenOn, screenOn);
+ updateTimeBasesLocked(false, !screenOn, uptime, realtime);
mNumChargeStepDurations = 0;
mLastChargeStepLevel = level;
mLastChargeStepTime = -1;
@@ -6475,7 +6491,7 @@
public int getDischargeAmountScreenOn() {
synchronized(this) {
int val = mDischargeAmountScreenOn;
- if (mOnBattery && mScreenOn
+ if (mOnBattery && mScreenState == Display.STATE_ON
&& mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
}
@@ -6486,7 +6502,7 @@
public int getDischargeAmountScreenOnSinceCharge() {
synchronized(this) {
int val = mDischargeAmountScreenOnSinceCharge;
- if (mOnBattery && mScreenOn
+ if (mOnBattery && mScreenState == Display.STATE_ON
&& mDischargeCurrentLevel < mDischargeScreenOnUnplugLevel) {
val += mDischargeScreenOnUnplugLevel-mDischargeCurrentLevel;
}
@@ -6497,7 +6513,7 @@
public int getDischargeAmountScreenOff() {
synchronized(this) {
int val = mDischargeAmountScreenOff;
- if (mOnBattery && !mScreenOn
+ if (mOnBattery && mScreenState != Display.STATE_ON
&& mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
}
@@ -6508,7 +6524,7 @@
public int getDischargeAmountScreenOffSinceCharge() {
synchronized(this) {
int val = mDischargeAmountScreenOffSinceCharge;
- if (mOnBattery && !mScreenOn
+ if (mOnBattery && mScreenState != Display.STATE_ON
&& mDischargeCurrentLevel < mDischargeScreenOffUnplugLevel) {
val += mDischargeScreenOffUnplugLevel-mDischargeCurrentLevel;
}
@@ -6915,12 +6931,13 @@
mStartCount++;
- mScreenOn = false;
+ mScreenState = Display.STATE_UNKNOWN;
mScreenOnTimer.readSummaryFromParcelLocked(in);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
mScreenBrightnessTimer[i].readSummaryFromParcelLocked(in);
}
- mInputEventCounter.readSummaryFromParcelLocked(in);
+ mInteractive = false;
+ mInteractiveTimer.readSummaryFromParcelLocked(in);
mPhoneOn = false;
mPhoneOnTimer.readSummaryFromParcelLocked(in);
for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -7175,7 +7192,7 @@
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
}
- mInputEventCounter.writeSummaryFromParcelLocked(out);
+ mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
@@ -7431,13 +7448,12 @@
mOnBatteryTimeBase.readFromParcel(in);
mOnBatteryScreenOffTimeBase.readFromParcel(in);
- mScreenOn = false;
+ mScreenState = Display.STATE_UNKNOWN;
mScreenOnTimer = new StopwatchTimer(null, -1, null, mOnBatteryTimeBase, in);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase,
in);
}
- mInputEventCounter = new Counter(mOnBatteryTimeBase, in);
mPhoneOn = false;
mPhoneOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -7461,19 +7477,25 @@
mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
mMobileRadioActiveUnknownCount = new LongSamplingCounter(mOnBatteryTimeBase, in);
mWifiOn = false;
- mWifiOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
+ mWifiOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase, in);
mGlobalWifiRunning = false;
- mGlobalWifiRunningTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
+ mGlobalWifiRunningTimer = new StopwatchTimer(null, -4, null, mOnBatteryTimeBase, in);
for (int i=0; i<NUM_WIFI_STATES; i++) {
mWifiStateTimer[i] = new StopwatchTimer(null, -600-i,
null, mOnBatteryTimeBase, in);
}
mBluetoothOn = false;
- mBluetoothOnTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in);
+ mBluetoothOnTimer = new StopwatchTimer(null, -5, null, mOnBatteryTimeBase, in);
for (int i=0; i< NUM_BLUETOOTH_STATES; i++) {
mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i,
null, mOnBatteryTimeBase, in);
}
+ mAudioOn = false;
+ mAudioOnTimer = new StopwatchTimer(null, -6, null, mOnBatteryTimeBase);
+ mVideoOn = false;
+ mVideoOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase);
+ mInteractive = false;
+ mInteractiveTimer = new StopwatchTimer(null, -8, null, mOnBatteryTimeBase, in);
mDischargeUnplugLevel = in.readInt();
mDischargePlugLevel = in.readInt();
mDischargeCurrentLevel = in.readInt();
@@ -7571,7 +7593,7 @@
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime);
}
- mInputEventCounter.writeToParcel(out);
+ mInteractiveTimer.writeToParcel(out, uSecRealtime);
mPhoneOnTimer.writeToParcel(out, uSecRealtime);
for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
@@ -7688,8 +7710,8 @@
pr.println("*** Screen brightness #" + i + ":");
mScreenBrightnessTimer[i].logState(pr, " ");
}
- pr.println("*** Input event counter:");
- mInputEventCounter.logState(pr, " ");
+ pr.println("*** Interactive timer:");
+ mInteractiveTimer.logState(pr, " ");
pr.println("*** Phone timer:");
mPhoneOnTimer.logState(pr, " ");
for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 6428e15..caa6b98 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -42,7 +42,7 @@
out int[] switches, out List<IBinder> binders);
void onPanelRevealed();
void onPanelHidden();
- void onNotificationClick(String pkg, String tag, int id, int userId);
+ void onNotificationClick(String key);
void onNotificationError(String pkg, String tag, int id,
int uid, int initialPid, String message, int userId);
void onClearAllNotifications(int userId);
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index a54b364..f6722a6 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -30,7 +30,7 @@
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
- public static <T> T checkNotNull(T reference) {
+ public static <T> T checkNotNull(final T reference) {
if (reference == null) {
throw new NullPointerException();
}
@@ -47,7 +47,7 @@
* @return the non-null reference that was validated
* @throws NullPointerException if {@code reference} is null
*/
- public static <T> T checkNotNull(T reference, Object errorMessage) {
+ public static <T> T checkNotNull(final T reference, final Object errorMessage) {
if (reference == null) {
throw new NullPointerException(String.valueOf(errorMessage));
}
@@ -61,7 +61,7 @@
* @param expression a boolean expression
* @throws IllegalStateException if {@code expression} is false
*/
- public static void checkState(boolean expression) {
+ public static void checkState(final boolean expression) {
if (!expression) {
throw new IllegalStateException();
}
@@ -71,11 +71,178 @@
* Check the requested flags, throwing if any requested flags are outside
* the allowed set.
*/
- public static void checkFlagsArgument(int requestedFlags, int allowedFlags) {
+ public static void checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
if ((requestedFlags & allowedFlags) != requestedFlags) {
throw new IllegalArgumentException("Requested flags 0x"
+ Integer.toHexString(requestedFlags) + ", but only 0x"
+ Integer.toHexString(allowedFlags) + " are allowed");
}
}
+
+ /**
+ * Ensures that that the argument numeric value is non-negative.
+ *
+ * @param value a numeric int value
+ * @param errorMessage the exception message to use if the check fails
+ * @return the validated numeric value
+ * @throws IllegalArgumentException if {@code value} was negative
+ */
+ public static int checkArgumentNonnegative(final int value, final String errorMessage) {
+ if (value < 0) {
+ throw new IllegalArgumentException(errorMessage);
+ }
+
+ return value;
+ }
+
+ /**
+ * Ensures that that the argument numeric value is non-negative.
+ *
+ * @param value a numeric long value
+ * @param errorMessage the exception message to use if the check fails
+ * @return the validated numeric value
+ * @throws IllegalArgumentException if {@code value} was negative
+ */
+ public static long checkArgumentNonnegative(final long value, final String errorMessage) {
+ if (value < 0) {
+ throw new IllegalArgumentException(errorMessage);
+ }
+
+ return value;
+ }
+
+ /**
+ * Ensures that that the argument numeric value is positive.
+ *
+ * @param value a numeric int value
+ * @param errorMessage the exception message to use if the check fails
+ * @return the validated numeric value
+ * @throws IllegalArgumentException if {@code value} was not positive
+ */
+ public static int checkArgumentPositive(final int value, final String errorMessage) {
+ if (value <= 0) {
+ throw new IllegalArgumentException(errorMessage);
+ }
+
+ return value;
+ }
+
+ /**
+ * Ensures that the argument floating point value is a finite number.
+ *
+ * <p>A finite number is defined to be both representable (that is, not NaN) and
+ * not infinite (that is neither positive or negative infinity).</p>
+ *
+ * @param value a floating point value
+ * @param valueName the name of the argument to use if the check fails
+ *
+ * @return the validated floating point value
+ *
+ * @throws IllegalArgumentException if {@code value} was not finite
+ */
+ public static float checkArgumentFinite(final float value, final String valueName) {
+ if (Float.isNaN(value)) {
+ throw new IllegalArgumentException(valueName + " must not be NaN");
+ } else if (Float.isInfinite(value)) {
+ throw new IllegalArgumentException(valueName + " must not be infinite");
+ }
+
+ return value;
+ }
+
+ /**
+ * Ensures that the argument floating point value is within the inclusive range.
+ *
+ * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
+ * will always be out of range.</p>
+ *
+ * @param value a floating point value
+ * @param lower the lower endpoint of the inclusive range
+ * @param upper the upper endpoint of the inclusive range
+ * @param valueName the name of the argument to use if the check fails
+ *
+ * @return the validated floating point value
+ *
+ * @throws IllegalArgumentException if {@code value} was not within the range
+ */
+ public static float checkArgumentInRange(float value, float lower, float upper,
+ String valueName) {
+ if (Float.isNaN(value)) {
+ throw new IllegalArgumentException(valueName + " must not be NaN");
+ } else if (value < lower) {
+ throw new IllegalArgumentException(
+ String.format(
+ "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
+ } else if (value > upper) {
+ throw new IllegalArgumentException(
+ String.format(
+ "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
+ }
+
+ return value;
+ }
+
+ /**
+ * Ensures that the array is not {@code null}, and none if its elements are {@code null}.
+ *
+ * @param value an array of boxed objects
+ * @param valueName the name of the argument to use if the check fails
+ *
+ * @return the validated array
+ *
+ * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
+ */
+ public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) {
+ if (value == null) {
+ throw new NullPointerException(valueName + " must not be null");
+ }
+
+ for (int i = 0; i < value.length; ++i) {
+ if (value[i] == null) {
+ throw new NullPointerException(
+ String.format("%s[%d] must not be null", valueName, i));
+ }
+ }
+
+ return value;
+ }
+
+ /**
+ * Ensures that all elements in the argument floating point array are within the inclusive range
+ *
+ * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
+ * will always be out of range.</p>
+ *
+ * @param value a floating point array of values
+ * @param lower the lower endpoint of the inclusive range
+ * @param upper the upper endpoint of the inclusive range
+ * @param valueName the name of the argument to use if the check fails
+ *
+ * @return the validated floating point value
+ *
+ * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
+ * @throws NullPointerException if the {@code value} was {@code null}
+ */
+ public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
+ String valueName) {
+ checkNotNull(value, valueName + " must not be null");
+
+ for (int i = 0; i < value.length; ++i) {
+ float v = value[i];
+
+ if (Float.isNaN(v)) {
+ throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN");
+ } else if (v < lower) {
+ throw new IllegalArgumentException(
+ String.format("%s[%d] is out of range of [%f, %f] (too low)",
+ valueName, i, lower, upper));
+ } else if (v > upper) {
+ throw new IllegalArgumentException(
+ String.format("%s[%d] is out of range of [%f, %f] (too high)",
+ valueName, i, lower, upper));
+ }
+ }
+
+ return value;
+ }
}
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index d664058..5a12893 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -53,6 +53,7 @@
private final MenuAdapter mAdapter;
private final boolean mOverflowOnly;
private final int mPopupMaxWidth;
+ private final int mPopupStyleAttr;
private View mAnchorView;
private ListPopupWindow mPopup;
@@ -72,20 +73,21 @@
private int mDropDownGravity = Gravity.NO_GRAVITY;
public MenuPopupHelper(Context context, MenuBuilder menu) {
- this(context, menu, null, false);
+ this(context, menu, null, false, com.android.internal.R.attr.popupMenuStyle);
}
public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView) {
- this(context, menu, anchorView, false);
+ this(context, menu, anchorView, false, com.android.internal.R.attr.popupMenuStyle);
}
- public MenuPopupHelper(Context context, MenuBuilder menu,
- View anchorView, boolean overflowOnly) {
+ public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView,
+ boolean overflowOnly, int popupStyleAttr) {
mContext = context;
mInflater = LayoutInflater.from(context);
mMenu = menu;
mAdapter = new MenuAdapter(mMenu);
mOverflowOnly = overflowOnly;
+ mPopupStyleAttr = popupStyleAttr;
final Resources res = context.getResources();
mPopupMaxWidth = Math.max(res.getDisplayMetrics().widthPixels / 2,
@@ -119,7 +121,7 @@
}
public boolean tryShow() {
- mPopup = new ListPopupWindow(mContext, null, com.android.internal.R.attr.popupMenuStyle);
+ mPopup = new ListPopupWindow(mContext, null, mPopupStyleAttr);
mPopup.setOnDismissListener(this);
mPopup.setOnItemClickListener(this);
mPopup.setAdapter(mAdapter);
@@ -272,7 +274,7 @@
@Override
public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
if (subMenu.hasVisibleItems()) {
- MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu, mAnchorView, false);
+ MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu, mAnchorView);
subPopup.setCallback(mPresenterCallback);
boolean preserveIconSpacing = false;
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index 01bee0c..19d58bf 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -576,7 +576,7 @@
}
public int getActionBarHideOffset() {
- return -((int) mActionBarTop.getTranslationY());
+ return mActionBarTop != null ? -((int) mActionBarTop.getTranslationY()) : 0;
}
public void setActionBarHideOffset(int offset) {
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
index 467d42e..674d084 100644
--- a/core/java/com/android/internal/widget/SwipeDismissLayout.java
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -35,7 +35,7 @@
public class SwipeDismissLayout extends FrameLayout {
private static final String TAG = "SwipeDismissLayout";
- private static final float TRANSLATION_MIN_ALPHA = 0.5f;
+ private static final float DISMISS_MIN_PROGRESS = 0.6f;
public interface OnDismissedListener {
void onDismissed(SwipeDismissLayout layout);
@@ -77,6 +77,8 @@
private OnDismissedListener mDismissedListener;
private OnSwipeProgressChangedListener mProgressListener;
+ private float mLastX;
+
public SwipeDismissLayout(Context context) {
super(context);
init(context);
@@ -95,7 +97,7 @@
private void init(Context context) {
ViewConfiguration vc = ViewConfiguration.get(getContext());
mSlop = vc.getScaledTouchSlop();
- mMinFlingVelocity = vc.getScaledMinimumFlingVelocity() * 16;
+ mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();
mAnimationTime = getContext().getResources().getInteger(
android.R.integer.config_shortAnimTime);
@@ -193,8 +195,8 @@
case MotionEvent.ACTION_MOVE:
mVelocityTracker.addMovement(ev);
+ mLastX = ev.getRawX();
updateSwiping(ev);
- updateDismiss(ev);
if (mSwiping) {
setProgress(ev.getRawX() - mDownX);
break;
@@ -256,20 +258,16 @@
float absVelocityX = Math.abs(velocityX);
float absVelocityY = Math.abs(mVelocityTracker.getYVelocity());
- if (deltaX > getWidth() / 2) {
- mDismissed = true;
- } else if (absVelocityX >= mMinFlingVelocity
- && absVelocityX <= mMaxFlingVelocity
- && absVelocityY < absVelocityX / 2
- && velocityX > 0
- && deltaX > 0) {
+ if (deltaX > (getWidth() * DISMISS_MIN_PROGRESS) &&
+ absVelocityX < mMinFlingVelocity &&
+ ev.getRawX() >= mLastX) {
mDismissed = true;
}
}
// Check if the user tried to undo this.
if (mDismissed && mSwiping) {
// Check if the user's finger is actually back
- if (deltaX < getWidth() / 2) {
+ if (deltaX < (getWidth() * DISMISS_MIN_PROGRESS)) {
mDismissed = false;
}
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index ee59c8a..8bd2e4f 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -92,6 +92,7 @@
android/graphics/BitmapFactory.cpp \
android/graphics/Camera.cpp \
android/graphics/Canvas.cpp \
+ android/graphics/CanvasProperty.cpp \
android/graphics/ColorFilter.cpp \
android/graphics/DrawFilter.cpp \
android/graphics/CreateJavaOutputStreamAdaptor.cpp \
@@ -140,6 +141,7 @@
android_util_FileObserver.cpp \
android/opengl/poly_clip.cpp.arm \
android/opengl/util.cpp.arm \
+ android_server_FingerprintManager.cpp \
android_server_NetworkManagementSocketTagger.cpp \
android_server_Watchdog.cpp \
android_ddm_DdmHandleNativeHeap.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index f964cd2..66fbb8e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -105,6 +105,7 @@
extern int register_android_content_XmlBlock(JNIEnv* env);
extern int register_android_emoji_EmojiFactory(JNIEnv* env);
extern int register_android_graphics_Canvas(JNIEnv* env);
+extern int register_android_graphics_CanvasProperty(JNIEnv* env);
extern int register_android_graphics_ColorFilter(JNIEnv* env);
extern int register_android_graphics_DrawFilter(JNIEnv* env);
extern int register_android_graphics_Matrix(JNIEnv* env);
@@ -1221,6 +1222,7 @@
REG_JNI(register_android_graphics_Camera),
REG_JNI(register_android_graphics_CreateJavaOutputStreamAdaptor),
REG_JNI(register_android_graphics_Canvas),
+ REG_JNI(register_android_graphics_CanvasProperty),
REG_JNI(register_android_graphics_ColorFilter),
REG_JNI(register_android_graphics_DrawFilter),
REG_JNI(register_android_graphics_Interpolator),
diff --git a/core/jni/android/graphics/CanvasProperty.cpp b/core/jni/android/graphics/CanvasProperty.cpp
new file mode 100644
index 0000000..70e2db5
--- /dev/null
+++ b/core/jni/android/graphics/CanvasProperty.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 20014 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 "jni.h"
+#include "GraphicsJNI.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include <utils/VirtualLightRefBase.h>
+#include <CanvasProperty.h>
+
+namespace android {
+
+using namespace uirenderer;
+
+#ifdef USE_OPENGL_RENDERER
+
+static jlong incRef(VirtualLightRefBase* ptr) {
+ ptr->incStrong(0);
+ return reinterpret_cast<jlong>(ptr);
+}
+
+static jlong createFloat(JNIEnv* env, jobject clazz, jfloat initialValue) {
+ return incRef(new CanvasPropertyPrimitive(initialValue));
+}
+
+static jlong createPaint(JNIEnv* env, jobject clazz, jlong paintPtr) {
+ const SkPaint* paint = reinterpret_cast<const SkPaint*>(paintPtr);
+ return incRef(new CanvasPropertyPaint(*paint));
+}
+
+static void unref(JNIEnv* env, jobject clazz, jlong containerPtr) {
+ reinterpret_cast<VirtualLightRefBase*>(containerPtr)->decStrong(0);
+}
+
+#endif
+
+// ----------------------------------------------------------------------------
+// JNI Glue
+// ----------------------------------------------------------------------------
+
+const char* const kClassPathName = "android/graphics/CanvasProperty";
+
+static JNINativeMethod gMethods[] = {
+#ifdef USE_OPENGL_RENDERER
+ { "nCreateFloat", "(F)J", (void*) createFloat },
+ { "nCreatePaint", "(J)J", (void*) createPaint },
+ { "nUnref", "(J)V", (void*) unref },
+#endif
+};
+
+int register_android_graphics_CanvasProperty(JNIEnv* env) {
+ return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index b78b131..621534e 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -221,7 +221,7 @@
}
fields.postEvent = env->GetStaticMethodID(clazz, "postEventFromNative",
- "(Ljava/lang/Object;)V");
+ "(Ljava/lang/ref/WeakReference;)V");
if (fields.postEvent == NULL) {
ALOGE("can't find android/graphics/SurfaceTexture.postEventFromNative");
}
@@ -338,7 +338,7 @@
static JNINativeMethod gSurfaceTextureMethods[] = {
{"nativeClassInit", "()V", (void*)SurfaceTexture_classInit },
- {"nativeInit", "(IZLjava/lang/Object;)V", (void*)SurfaceTexture_init },
+ {"nativeInit", "(IZLjava/lang/ref/WeakReference;)V", (void*)SurfaceTexture_init },
{"nativeFinalize", "()V", (void*)SurfaceTexture_finalize },
{"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize },
{"nativeUpdateTexImage", "()V", (void*)SurfaceTexture_updateTexImage },
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index 957f95c..05a99a3 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -18,8 +18,12 @@
// #define LOG_NDEBUG 0
// #define LOG_NNDEBUG 0
#define LOG_TAG "CameraMetadata-JNI"
+#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/RefBase.h>
+#include <utils/Vector.h>
+#include <utils/SortedVector.h>
+#include <utils/KeyedVector.h>
#include <string.h>
#include "jni.h"
@@ -483,12 +487,20 @@
ALOGV("%s (key = '%s')", __FUNCTION__, key);
+ sp<VendorTagDescriptor> vTags = VendorTagDescriptor::getGlobalVendorTagDescriptor();
+
+ SortedVector<String8> vendorSections = vTags->getAllSectionNames();
+ size_t vendorSectionCount = vendorSections.size();
+
// First, find the section by the longest string match
const char *section = NULL;
size_t sectionIndex = 0;
size_t sectionLength = 0;
- for (size_t i = 0; i < ANDROID_SECTION_COUNT; ++i) {
- const char *str = camera_metadata_section_names[i];
+ size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
+ for (size_t i = 0; i < totalSectionCount; ++i) {
+
+ const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
+ vendorSections[i - ANDROID_SECTION_COUNT].string();
ALOGVV("%s: Trying to match against section '%s'",
__FUNCTION__, str);
if (strstr(key, str) == key) { // key begins with the section name
@@ -502,12 +514,11 @@
sectionIndex = i;
sectionLength = strLength;
- ALOGVV("%s: Found new best section (idx %d)", __FUNCTION__, sectionIndex);
+ ALOGVV("%s: Found new best section (%s)", __FUNCTION__, section);
}
}
}
- // TODO: vendor ext
// TODO: Make above get_camera_metadata_section_from_name ?
if (section == NULL) {
@@ -524,33 +535,47 @@
if (sectionLength + 1 >= keyLength) {
jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
"Key length too short for key '%s')", key);
+ return 0;
}
// Match rest of name against the tag names in that section only
- uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
- tagBegin = camera_metadata_section_bounds[sectionIndex][0];
- tagEnd = camera_metadata_section_bounds[sectionIndex][1];
+ uint32_t tag = 0;
+ if (sectionIndex < ANDROID_SECTION_COUNT) {
+ // Match built-in tags (typically android.*)
+ uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
+ tagBegin = camera_metadata_section_bounds[sectionIndex][0];
+ tagEnd = camera_metadata_section_bounds[sectionIndex][1];
- uint32_t tag;
- for (tag = tagBegin; tag < tagEnd; ++tag) {
- const char *tagName = get_camera_metadata_tag_name(tag);
+ for (tag = tagBegin; tag < tagEnd; ++tag) {
+ const char *tagName = get_camera_metadata_tag_name(tag);
- if (strcmp(keyTagName, tagName) == 0) {
- ALOGV("%s: Found matched tag '%s' (%d)",
- __FUNCTION__, tagName, tag);
- break;
+ if (strcmp(keyTagName, tagName) == 0) {
+ ALOGV("%s: Found matched tag '%s' (%d)",
+ __FUNCTION__, tagName, tag);
+ break;
+ }
+ }
+
+ if (tag == tagEnd) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+ "Could not find tag name for key '%s')", key);
+ return 0;
+ }
+ } else {
+ // Match vendor tags (typically com.*)
+ const String8 sectionName(section);
+ const String8 tagName(keyTagName);
+
+ status_t res = OK;
+ if ((res = vTags->lookupTag(tagName, sectionName, &tag)) != OK) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+ "%s: No vendor tag matches key '%s'", __FUNCTION__, key);
+ return 0;
}
}
- // TODO: vendor ext
// TODO: Make above get_camera_metadata_tag_from_name ?
- if (tag == tagEnd) {
- jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
- "Could not find tag name for key '%s')", key);
- return 0;
- }
-
return tag;
}
diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h
index f4bab26..fedb1b2 100644
--- a/core/jni/android_media_AudioFormat.h
+++ b/core/jni/android_media_AudioFormat.h
@@ -22,6 +22,7 @@
// keep these values in sync with AudioFormat.java
#define ENCODING_PCM_16BIT 2
#define ENCODING_PCM_8BIT 3
+#define ENCODING_PCM_FLOAT 4
static inline audio_format_t audioFormatToNative(int audioFormat)
{
@@ -30,6 +31,8 @@
return AUDIO_FORMAT_PCM_16_BIT;
case ENCODING_PCM_8BIT:
return AUDIO_FORMAT_PCM_8_BIT;
+ case ENCODING_PCM_FLOAT:
+ return AUDIO_FORMAT_PCM_FLOAT;
default:
return AUDIO_FORMAT_INVALID;
}
diff --git a/core/jni/android_server_FingerprintManager.cpp b/core/jni/android_server_FingerprintManager.cpp
new file mode 100644
index 0000000..f8a1fd9
--- /dev/null
+++ b/core/jni/android_server_FingerprintManager.cpp
@@ -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.
+ */
+
+#define LOG_TAG "Fingerprint-JNI"
+
+#include "JNIHelp.h"
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/Log.h>
+#include <utils/Log.h>
+
+namespace android {
+
+static struct {
+ jclass clazz;
+ jmethodID notify;
+} gFingerprintManagerClassInfo;
+
+static jint nativeEnroll(JNIEnv* env, jobject clazz, jint timeout) {
+ return -1; // TODO
+}
+
+static jint nativeRemove(JNIEnv* env, jobject clazz, jint fingerprintId) {
+ return -1; // TODO
+}
+
+// ----------------------------------------------------------------------------
+
+static const JNINativeMethod g_methods[] = {
+ { "nativeEnroll", "(I)I", (void*)nativeEnroll },
+ { "nativeRemove", "(I)I", (void*)nativeRemove },
+};
+
+#define FIND_CLASS(var, className) \
+ var = env->FindClass(className); \
+ LOG_FATAL_IF(! var, "Unable to find class " className); \
+ var = jclass(env->NewGlobalRef(var));
+
+#define GET_STATIC_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
+ var = env->GetStaticMethodID(clazz, methodName, fieldDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find static method" methodName);
+
+#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
+ var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find method" methodName);
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+ var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_FingerprintManager(JNIEnv* env) {
+ FIND_CLASS(gFingerprintManagerClassInfo.clazz,
+ "android/service/fingerprint/FingerprintManager");
+ GET_METHOD_ID(gFingerprintManagerClassInfo.notify, gFingerprintManagerClassInfo.clazz,
+ "notify", "(III)V");
+ return AndroidRuntime::registerNativeMethods(
+ env, "com/android/service/fingerprint/FingerprintManager", g_methods, NELEM(g_methods));
+}
+
+} // namespace android
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index ef5ebd0..3aa179d 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -49,6 +49,7 @@
#include <Stencil.h>
#include <Rect.h>
#include <RenderNode.h>
+#include <CanvasProperty.h>
#include <TextLayout.h>
#include <TextLayoutCache.h>
@@ -544,6 +545,16 @@
renderer->drawCircle(x, y, radius, paint);
}
+static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz,
+ jlong rendererPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
+ OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+ CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
+ CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
+ CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
+ CanvasPropertyPaint* paintProp = reinterpret_cast<CanvasPropertyPaint*>(paintPropPtr);
+ renderer->drawCircle(xProp, yProp, radiusProp, paintProp);
+}
+
static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
jlong paintPtr) {
@@ -1041,6 +1052,7 @@
{ "nDrawRects", "(J[FIJ)V", (void*) android_view_GLES20Canvas_drawRects },
{ "nDrawRoundRect", "(JFFFFFFJ)V", (void*) android_view_GLES20Canvas_drawRoundRect },
{ "nDrawCircle", "(JFFFJ)V", (void*) android_view_GLES20Canvas_drawCircle },
+ { "nDrawCircle", "(JJJJJ)V", (void*) android_view_GLES20Canvas_drawCircleProps },
{ "nDrawOval", "(JFFFFJ)V", (void*) android_view_GLES20Canvas_drawOval },
{ "nDrawArc", "(JFFFFFFZJ)V", (void*) android_view_GLES20Canvas_drawArc },
{ "nDrawPoints", "(J[FIIJ)V", (void*) android_view_GLES20Canvas_drawPoints },
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index b92c992..3be013b 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -16,8 +16,6 @@
#define LOG_TAG "OpenGLRenderer"
-#include "android_view_RenderNodeAnimator.h"
-
#include "jni.h"
#include "GraphicsJNI.h"
#include <nativehelper/JNIHelp.h>
@@ -47,46 +45,93 @@
return env;
}
-RenderNodeAnimator::RenderNodeAnimator(JNIEnv* env, jobject weakThis,
- RenderProperty property, DeltaValueType deltaType, float delta)
- : RenderPropertyAnimator(property, deltaType, delta) {
- mWeakThis = env->NewGlobalRef(weakThis);
- env->GetJavaVM(&mJvm);
-}
+class AnimationListenerBridge : public AnimationListener {
+public:
+ // This holds a strong reference to a Java WeakReference<T> object. This avoids
+ // cyclic-references-of-doom. If you think "I know, just use NewWeakGlobalRef!"
+ // then you end up with basically a PhantomReference, which is totally not
+ // what we want.
+ AnimationListenerBridge(JNIEnv* env, jobject weakThis) {
+ mWeakThis = env->NewGlobalRef(weakThis);
+ env->GetJavaVM(&mJvm);
+ }
-RenderNodeAnimator::~RenderNodeAnimator() {
- JNIEnv* env = getEnv(mJvm);
- env->DeleteGlobalRef(mWeakThis);
- mWeakThis = NULL;
-}
+ virtual ~AnimationListenerBridge() {
+ JNIEnv* env = getEnv(mJvm);
+ env->DeleteGlobalRef(mWeakThis);
+ mWeakThis = NULL;
+ }
-void RenderNodeAnimator::callOnFinished() {
- JNIEnv* env = getEnv(mJvm);
- env->CallStaticVoidMethod(
- gRenderNodeAnimatorClassInfo.clazz,
- gRenderNodeAnimatorClassInfo.callOnFinished,
- mWeakThis);
-}
+ virtual void onAnimationFinished(BaseAnimator*) {
+ JNIEnv* env = getEnv(mJvm);
+ env->CallStaticVoidMethod(
+ gRenderNodeAnimatorClassInfo.clazz,
+ gRenderNodeAnimatorClassInfo.callOnFinished,
+ mWeakThis);
+ }
-static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis,
- jint property, jint deltaType, jfloat deltaValue) {
- LOG_ALWAYS_FATAL_IF(property < 0 || property > RenderNodeAnimator::ALPHA,
+private:
+ JavaVM* mJvm;
+ jobject mWeakThis;
+};
+
+static inline RenderPropertyAnimator::RenderProperty toRenderProperty(jint property) {
+ LOG_ALWAYS_FATAL_IF(property < 0 || property > RenderPropertyAnimator::ALPHA,
"Invalid property %d", property);
+ return static_cast<RenderPropertyAnimator::RenderProperty>(property);
+}
+
+static inline RenderPropertyAnimator::DeltaValueType toDeltaType(jint deltaType) {
LOG_ALWAYS_FATAL_IF(deltaType != RenderPropertyAnimator::DELTA
&& deltaType != RenderPropertyAnimator::ABSOLUTE,
"Invalid delta type %d", deltaType);
+ return static_cast<RenderPropertyAnimator::DeltaValueType>(deltaType);
+}
- RenderNodeAnimator* animator = new RenderNodeAnimator(env, weakThis,
- static_cast<RenderPropertyAnimator::RenderProperty>(property),
- static_cast<RenderPropertyAnimator::DeltaValueType>(deltaType),
- deltaValue);
+static inline CanvasPropertyPaintAnimator::PaintField toPaintField(jint field) {
+ LOG_ALWAYS_FATAL_IF(field < 0
+ || field > CanvasPropertyPaintAnimator::ALPHA,
+ "Invalid paint field %d", field);
+ return static_cast<CanvasPropertyPaintAnimator::PaintField>(field);
+}
+
+static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis,
+ jint propertyRaw, jint deltaTypeRaw, jfloat deltaValue) {
+ RenderPropertyAnimator::RenderProperty property = toRenderProperty(propertyRaw);
+ RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
+
+ BaseAnimator* animator = new RenderPropertyAnimator(property, deltaType, deltaValue);
animator->incStrong(0);
+ animator->setListener(new AnimationListenerBridge(env, weakThis));
+ return reinterpret_cast<jlong>( animator );
+}
+
+static jlong createCanvasPropertyFloatAnimator(JNIEnv* env, jobject clazz,
+ jobject weakThis, jlong canvasPropertyPtr, jint deltaTypeRaw, jfloat deltaValue) {
+ RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
+ CanvasPropertyPrimitive* canvasProperty = reinterpret_cast<CanvasPropertyPrimitive*>(canvasPropertyPtr);
+ BaseAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, deltaType, deltaValue);
+ animator->incStrong(0);
+ animator->setListener(new AnimationListenerBridge(env, weakThis));
+ return reinterpret_cast<jlong>( animator );
+}
+
+static jlong createCanvasPropertyPaintAnimator(JNIEnv* env, jobject clazz,
+ jobject weakThis, jlong canvasPropertyPtr, jint paintFieldRaw,
+ jint deltaTypeRaw, jfloat deltaValue) {
+ RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw);
+ CanvasPropertyPaint* canvasProperty = reinterpret_cast<CanvasPropertyPaint*>(canvasPropertyPtr);
+ CanvasPropertyPaintAnimator::PaintField paintField = toPaintField(paintFieldRaw);
+ BaseAnimator* animator = new CanvasPropertyPaintAnimator(
+ canvasProperty, paintField, deltaType, deltaValue);
+ animator->incStrong(0);
+ animator->setListener(new AnimationListenerBridge(env, weakThis));
return reinterpret_cast<jlong>( animator );
}
static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jint duration) {
LOG_ALWAYS_FATAL_IF(duration < 0, "Duration cannot be negative");
- RenderNodeAnimator* animator = reinterpret_cast<RenderNodeAnimator*>(animatorPtr);
+ BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr);
animator->setDuration(duration);
}
@@ -106,6 +151,8 @@
static JNINativeMethod gMethods[] = {
#ifdef USE_OPENGL_RENDERER
{ "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IIF)J", (void*) createAnimator },
+ { "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyFloatAnimator },
+ { "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIIF)J", (void*) createCanvasPropertyPaintAnimator },
{ "nSetDuration", "(JI)V", (void*) setDuration },
{ "nUnref", "(J)V", (void*) unref },
#endif
diff --git a/core/jni/android_view_RenderNodeAnimator.h b/core/jni/android_view_RenderNodeAnimator.h
deleted file mode 100644
index 760ca91..0000000
--- a/core/jni/android_view_RenderNodeAnimator.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2012 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 "jni.h"
-
-#ifdef USE_OPENGL_RENDERER
-
-#include <Animator.h>
-
-namespace android {
-
-class RenderNodeAnimator : public uirenderer::RenderPropertyAnimator {
-public:
- RenderNodeAnimator(JNIEnv* env, jobject callbackObject,
- RenderProperty property, DeltaValueType deltaType, float delta);
- virtual ~RenderNodeAnimator();
-
- void callOnFinished();
-
-private:
- JavaVM* mJvm;
- jobject mWeakThis;
-};
-
-}
-
-#endif
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index c293c7a..5a935a9 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -50,6 +50,8 @@
"android/view/Surface$OutOfResourcesException";
static struct {
+ jclass clazz;
+ jmethodID ctor;
jfieldID width;
jfieldID height;
jfieldID refreshRate;
@@ -346,24 +348,49 @@
SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect);
}
-static jboolean nativeGetDisplayInfo(JNIEnv* env, jclass clazz,
- jobject tokenObj, jobject infoObj) {
+static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz,
+ jobject tokenObj) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
- if (token == NULL) return JNI_FALSE;
+ if (token == NULL) return NULL;
- DisplayInfo info;
- if (SurfaceComposerClient::getDisplayInfo(token, &info)) {
- return JNI_FALSE;
+ Vector<DisplayInfo> configs;
+ if (SurfaceComposerClient::getDisplayConfigs(token, &configs) != NO_ERROR ||
+ configs.size() == 0) {
+ return NULL;
}
- env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w);
- env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h);
- env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps);
- env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density);
- env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi);
- env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi);
- env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure);
- return JNI_TRUE;
+ jobjectArray configArray = env->NewObjectArray(configs.size(),
+ gPhysicalDisplayInfoClassInfo.clazz, NULL);
+
+ for (size_t c = 0; c < configs.size(); ++c) {
+ const DisplayInfo& info = configs[c];
+ jobject infoObj = env->NewObject(gPhysicalDisplayInfoClassInfo.clazz,
+ gPhysicalDisplayInfoClassInfo.ctor);
+ env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w);
+ env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h);
+ env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps);
+ env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density);
+ env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi);
+ env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi);
+ env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure);
+ env->SetObjectArrayElement(configArray, static_cast<jsize>(c), infoObj);
+ env->DeleteLocalRef(infoObj);
+ }
+
+ return configArray;
+}
+
+static jint nativeGetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj) {
+ sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+ if (token == NULL) return -1;
+ return static_cast<jint>(SurfaceComposerClient::getActiveConfig(token));
+}
+
+static jboolean nativeSetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj, jint id) {
+ sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+ if (token == NULL) return JNI_FALSE;
+ status_t err = SurfaceComposerClient::setActiveConfig(token, static_cast<int>(id));
+ return err == NO_ERROR ? JNI_TRUE : JNI_FALSE;
}
static void nativeBlankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
@@ -576,8 +603,12 @@
(void*)nativeSetDisplayLayerStack },
{"nativeSetDisplayProjection", "(Landroid/os/IBinder;IIIIIIIII)V",
(void*)nativeSetDisplayProjection },
- {"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/SurfaceControl$PhysicalDisplayInfo;)Z",
- (void*)nativeGetDisplayInfo },
+ {"nativeGetDisplayConfigs", "(Landroid/os/IBinder;)[Landroid/view/SurfaceControl$PhysicalDisplayInfo;",
+ (void*)nativeGetDisplayConfigs },
+ {"nativeGetActiveConfig", "(Landroid/os/IBinder;)I",
+ (void*)nativeGetActiveConfig },
+ {"nativeSetActiveConfig", "(Landroid/os/IBinder;I)Z",
+ (void*)nativeSetActiveConfig },
{"nativeBlankDisplay", "(Landroid/os/IBinder;)V",
(void*)nativeBlankDisplay },
{"nativeUnblankDisplay", "(Landroid/os/IBinder;)V",
@@ -598,6 +629,9 @@
sSurfaceControlMethods, NELEM(sSurfaceControlMethods));
jclass clazz = env->FindClass("android/view/SurfaceControl$PhysicalDisplayInfo");
+ gPhysicalDisplayInfoClassInfo.clazz = static_cast<jclass>(env->NewGlobalRef(clazz));
+ gPhysicalDisplayInfoClassInfo.ctor = env->GetMethodID(gPhysicalDisplayInfoClassInfo.clazz,
+ "<init>", "()V");
gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I");
gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I");
gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F");
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 58fc1e1..6ff28e3 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -26,7 +26,7 @@
#include <android_runtime/android_view_Surface.h>
#include <system/window.h>
-#include "android_view_RenderNodeAnimator.h"
+#include <Animator.h>
#include <RenderNode.h>
#include <renderthread/RenderProxy.h>
#include <renderthread/RenderTask.h>
@@ -67,26 +67,34 @@
jobject mRunnable;
};
+class OnFinishedEvent {
+public:
+ OnFinishedEvent(BaseAnimator* animator, AnimationListener* listener)
+ : animator(animator), listener(listener) {}
+ sp<BaseAnimator> animator;
+ sp<AnimationListener> listener;
+};
+
class InvokeAnimationListeners : public MessageHandler {
public:
- InvokeAnimationListeners(std::vector< sp<RenderNodeAnimator> >& animators) {
- mAnimators.swap(animators);
+ InvokeAnimationListeners(std::vector<OnFinishedEvent>& events) {
+ mOnFinishedEvents.swap(events);
}
- static void callOnFinished(const sp<RenderNodeAnimator>& animator) {
- animator->callOnFinished();
+ static void callOnFinished(OnFinishedEvent& event) {
+ event.listener->onAnimationFinished(event.animator.get());
}
virtual void handleMessage(const Message& message) {
- std::for_each(mAnimators.begin(), mAnimators.end(), callOnFinished);
- mAnimators.clear();
+ std::for_each(mOnFinishedEvents.begin(), mOnFinishedEvents.end(), callOnFinished);
+ mOnFinishedEvents.clear();
}
private:
- std::vector< sp<RenderNodeAnimator> > mAnimators;
+ std::vector<OnFinishedEvent> mOnFinishedEvents;
};
-class RootRenderNode : public RenderNode, public AnimationListener {
+class RootRenderNode : public RenderNode, public AnimationHook {
public:
RootRenderNode() : RenderNode() {
mLooper = Looper::getForThread();
@@ -96,27 +104,27 @@
virtual ~RootRenderNode() {}
- void onAnimationFinished(const sp<RenderPropertyAnimator>& animator) {
- mFinishedAnimators.push_back(
- reinterpret_cast<RenderNodeAnimator*>(animator.get()));
+ virtual void callOnFinished(BaseAnimator* animator, AnimationListener* listener) {
+ OnFinishedEvent event(animator, listener);
+ mOnFinishedEvents.push_back(event);
}
virtual void prepareTree(TreeInfo& info) {
- info.animationListener = this;
+ info.animationHook = this;
RenderNode::prepareTree(info);
- info.animationListener = NULL;
+ info.animationHook = NULL;
// post all the finished stuff
- if (mFinishedAnimators.size()) {
+ if (mOnFinishedEvents.size()) {
sp<InvokeAnimationListeners> message
- = new InvokeAnimationListeners(mFinishedAnimators);
+ = new InvokeAnimationListeners(mOnFinishedEvents);
mLooper->sendMessage(message, 0);
}
}
private:
sp<Looper> mLooper;
- std::vector< sp<RenderNodeAnimator> > mFinishedAnimators;
+ std::vector<OnFinishedEvent> mOnFinishedEvents;
};
static void android_view_ThreadedRenderer_postToRenderThread(JNIEnv* env, jobject clazz,
@@ -144,6 +152,18 @@
delete proxy;
}
+static void android_view_ThreadedRenderer_setFrameInterval(JNIEnv* env, jobject clazz,
+ jlong proxyPtr, jlong frameIntervalNanos) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ proxy->setFrameInterval(frameIntervalNanos);
+}
+
+static jboolean android_view_ThreadedRenderer_loadSystemProperties(JNIEnv* env, jobject clazz,
+ jlong proxyPtr) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ return proxy->loadSystemProperties();
+}
+
static jboolean android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz,
jlong proxyPtr, jobject jsurface) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -177,11 +197,11 @@
proxy->setup(width, height);
}
-static void android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jint dirtyLeft, jint dirtyTop,
+static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
+ jlong proxyPtr, jlong frameTimeNanos, jint dirtyLeft, jint dirtyTop,
jint dirtyRight, jint dirtyBottom) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- proxy->syncAndDrawFrame(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
+ return proxy->syncAndDrawFrame(frameTimeNanos, dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
}
static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, jobject clazz,
@@ -253,11 +273,13 @@
{ "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
{ "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
{ "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
+ { "nSetFrameInterval", "(JJ)V", (void*) android_view_ThreadedRenderer_setFrameInterval },
+ { "nLoadSystemProperties", "(J)Z", (void*) android_view_ThreadedRenderer_loadSystemProperties },
{ "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
{ "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
{ "nPauseSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_pauseSurface },
{ "nSetup", "(JII)V", (void*) android_view_ThreadedRenderer_setup },
- { "nSyncAndDrawFrame", "(JIIII)V", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
+ { "nSyncAndDrawFrame", "(JJIIII)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
{ "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface },
{ "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
{ "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3d3e86f..241500a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1279,7 +1279,7 @@
or recently running tasks. -->
<permission android:name="android.permission.GET_TASKS"
android:permissionGroup="android.permission-group.APP_INFO"
- android:protectionLevel="dangerous"
+ android:protectionLevel="signature|system"
android:label="@string/permlab_getTasks"
android:description="@string/permdesc_getTasks" />
<!-- @hide Allows an application to call APIs that allow it to do interactions
@@ -2793,7 +2793,7 @@
<receiver android:name="com.android.server.BootReceiver"
android:primaryUserOnly="true">
- <intent-filter>
+ <intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
diff --git a/core/res/res/anim/popup_enter_quantum.xml b/core/res/res/anim/popup_enter_quantum.xml
new file mode 100644
index 0000000..79de26b
--- /dev/null
+++ b/core/res/res/anim/popup_enter_quantum.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false" >
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+ android:interpolator="@interpolator/decelerate_cubic"
+ android:duration="@android:integer/config_activityShortDur" />
+</set>
diff --git a/core/res/res/anim/popup_exit_quantum.xml b/core/res/res/anim/popup_exit_quantum.xml
new file mode 100644
index 0000000..7d7d5c5
--- /dev/null
+++ b/core/res/res/anim/popup_exit_quantum.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false" >
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+ android:interpolator="@interpolator/decelerate_cubic"
+ android:duration="@android:integer/config_activityShortDur"/>
+</set>
diff --git a/core/res/res/drawable/popup_background_quantum.xml b/core/res/res/drawable/popup_background_quantum.xml
new file mode 100644
index 0000000..7e5b003
--- /dev/null
+++ b/core/res/res/drawable/popup_background_quantum.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+
+ <corners
+ android:radius="2dp" />
+ <solid
+ android:color="?attr/colorBackground" />
+
+</shape>
diff --git a/core/res/res/layout/voice_interaction_session.xml b/core/res/res/layout/voice_interaction_session.xml
new file mode 100644
index 0000000..48b6579
--- /dev/null
+++ b/core/res/res/layout/voice_interaction_session.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/layout/alert_dialog.xml
+**
+** 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.
+*/
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+</FrameLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 20d306d..4358dd3 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="UNIT">%2$s</xliff:g><xliff:g id="NUMBER">%1$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dae"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> uur"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> uur"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> uur"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> uur <xliff:g id="MINUTES">%2$d</xliff:g> minute"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> uur <xliff:g id="MINUTES">%2$d</xliff:g> minuut"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> minute"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> minuut <xliff:g id="SECONDS">%2$d</xliff:g> sekondes"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> minuut <xliff:g id="SECONDS">%2$d</xliff:g> sekond"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sekondes"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sekonde"</string>
<string name="untitled" msgid="4638956954852782576">"<Titelloos>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Veiligmodus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-stelsel"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Persoonlik"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Werk"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Dienste wat jou geld kos"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Doen dinge wat jou geld kan kos."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Jou boodskappe"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 04bfee5..7fac03f 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> ቀኖች"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> ቀን <xliff:g id="HOURS">%2$d</xliff:g> ሰዓ"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> ቀን <xliff:g id="HOURS">%2$d</xliff:g> ሰዓ"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ሰዓ"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ሰዓ <xliff:g id="MINUTES">%2$d</xliff:g> ደቂቃ"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ሰዓ <xliff:g id="MINUTES">%2$d</xliff:g> ደቂቃ"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> ደቂቃዎች"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> ደቂቃ <xliff:g id="SECONDS">%2$d</xliff:g> ሴ"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> ደቂቃ <xliff:g id="SECONDS">%2$d</xliff:g> ሴ"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> ሴ"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> ሴ"</string>
<string name="untitled" msgid="4638956954852782576">"<ርዕስ አልባ>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"የሚያስተማምን ሁነታ"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android ስርዓት"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"የግል"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"ስራ"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"ገንዘብ የሚያስወጥዎ አገልግሎቶች"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"ገንዘብ የሚያስወጡህን ነገሮች አድርግ።"</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"መልዕክቶችዎ"</string>
@@ -1077,7 +1068,7 @@
</plurals>
<plurals name="in_num_days">
<item quantity="one" msgid="5413088743009839518">"ነገ"</item>
- <item quantity="other" msgid="5109449375100953247">"በ<xliff:g id="COUNT">%d</xliff:g> ቀናት"</item>
+ <item quantity="other" msgid="5109449375100953247">"በ<xliff:g id="COUNT">%d</xliff:g> ቀኖች"</item>
</plurals>
<plurals name="abbrev_num_seconds_ago">
<item quantity="one" msgid="1849036840200069118">"1 ሴኮንድ በፊት"</item>
@@ -1109,7 +1100,7 @@
</plurals>
<plurals name="abbrev_in_num_days">
<item quantity="one" msgid="2178576254385739855">"ነገ"</item>
- <item quantity="other" msgid="2973062968038355991">"በ<xliff:g id="COUNT">%d</xliff:g> ቀናት"</item>
+ <item quantity="other" msgid="2973062968038355991">"በ<xliff:g id="COUNT">%d</xliff:g> ቀኖች"</item>
</plurals>
<string name="preposition_for_date" msgid="9093949757757445117">"በ <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"በ <xliff:g id="TIME">%s</xliff:g>"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 83168e4..a32c74c 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"تيرابايت"</string>
<string name="petabyteShort" msgid="5637816680144990219">"بيتابايت"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> يوم"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> يوم <xliff:g id="HOURS">%2$d</xliff:g> ساعة"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> يوم <xliff:g id="HOURS">%2$d</xliff:g> ساعة"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ساعة"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ساعة <xliff:g id="MINUTES">%2$d</xliff:g> دقيقة"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ساعة <xliff:g id="MINUTES">%2$d</xliff:g> دقيقة"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> دقيقة"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> دقيقة <xliff:g id="SECONDS">%2$d</xliff:g> ثانية"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> دقيقة <xliff:g id="SECONDS">%2$d</xliff:g> ثانية"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> ثانية"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> ثانية"</string>
<string name="untitled" msgid="4638956954852782576">"<بلا عنوان>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"الوضع الآمن"</string>
<string name="android_system_label" msgid="6577375335728551336">"نظام Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"شخصي"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"عمل"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"الخدمات التي تكلفك المال"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"يمكنك تنفيذ إجراءات يمكن أن تكلفك مالاً."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"رسائلك"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 2d22cdc..3ebe798 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"ТБ"</string>
<string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> дни"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> ден <xliff:g id="HOURS">%2$d</xliff:g> ч"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> ден <xliff:g id="HOURS">%2$d</xliff:g> ч"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ч"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ч <xliff:g id="MINUTES">%2$d</xliff:g> мин"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ч <xliff:g id="MINUTES">%2$d</xliff:g> мин"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> мин"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> мин <xliff:g id="SECONDS">%2$d</xliff:g> сек"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> мин <xliff:g id="SECONDS">%2$d</xliff:g> сек"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> сек"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> сек"</string>
<string name="untitled" msgid="4638956954852782576">"<Без заглавие>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Безопасен режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Системно от Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Личен"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Служебен"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Услуги, които ви струват пари"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Извършват неща, които могат да ви струват пари."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Вашите съобщения"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index cfb77d3..a767e7f 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dies"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dia <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dia <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> hores"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> minuts"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
<string name="untitled" msgid="4638956954852782576">"<Sense títol>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"+999"</string>
<string name="safeMode" msgid="2788228061547930246">"Mode segur"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Feina"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serveis de pagament"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Dur a terme activitats de pagament."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Missatges"</string>
@@ -409,8 +400,8 @@
<string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permet que el titular vinculi a la interfície de nivell superior d\'un servei de VPN. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"enllaça amb un fons de pantalla"</string>
<string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permet que el titular vinculi a la interfície de nivell superior d\'un fons de pantalla. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
- <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"vinculació amb una eina d\'interacció de veu"</string>
- <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permet que el titular es vinculi amb la interfície de nivell superior d\'un servei d\'interacció de veu. No ha de ser mai necessari per a aplicacions normals."</string>
+ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"enllaçar amb una eina d\'interacció de veu"</string>
+ <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permet enllaçar amb la interfície de nivell superior d\'un servei d\'interacció de veu. No ha de ser mai necessari per a aplicacions normals."</string>
<string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"vincula a una pantalla remota"</string>
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permet que el titular es vinculi a la interfície de nivell superior d\'una pantalla remota. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincula a un servei de widget"</string>
@@ -723,8 +714,8 @@
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet que l\'aplicació recuperi, examini i esborri les notificacions, incloses les que han publicat altres aplicacions."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vincula a un servei oient de notificacions"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet que el titular vinculi la interfície de nivell superior d\'un servei oient de notificacions. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
- <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"vinculació amb el servei d\'un proveïdor de condicions"</string>
- <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permet que el titular es vinculi amb la interfície de nivell superior del servei d\'un proveïdor de condicions. No ha de ser mai necessari per a aplicacions normals."</string>
+ <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"enllaçar amb el servei de proveïdor de condicions"</string>
+ <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permet enllaçar amb la interfície de nivell superior d\'un servei de proveïdor de condicions. No ha de ser mai necessari per a aplicacions normals."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invoca l\'aplicació de configuració proporcionada per l\'operador"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permet que el titular invoqui l\'aplicació de configuració proporcionada per l\'operador. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"conèixer les observacions sobre les condicions de la xarxa"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 868f899..1c4e8b8 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> d"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> d <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> d <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
<string name="untitled" msgid="4638956954852782576">"<Bez názvu>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Nouzový režim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Osobní"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Práce"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Zpoplatněné služby"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Provádět činnosti, které vás mohou stát peníze."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Vaše zprávy"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 206db12..1724de1 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"Tb"</string>
<string name="petabyteShort" msgid="5637816680144990219">"Pb"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dage"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> t."</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> t."</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> timer"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> t. <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> t. <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min."</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sek."</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sek."</string>
<string name="untitled" msgid="4638956954852782576">"<Uden titel>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Sikker tilstand"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Personlig"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Arbejde"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Tjenester, der koster dig penge"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Gør ting, der kan koste dig penge."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Dine beskeder"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 87d4aa0..e527521 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> Tage"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> Tag <xliff:g id="HOURS">%2$d</xliff:g> Std."</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> Tag <xliff:g id="HOURS">%2$d</xliff:g> Std."</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> Std."</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> Std. <xliff:g id="MINUTES">%2$d</xliff:g> Min."</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> Std. <xliff:g id="MINUTES">%2$d</xliff:g> Min."</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> Min."</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> Min. <xliff:g id="SECONDS">%2$d</xliff:g> Sek."</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> Min. <xliff:g id="SECONDS">%2$d</xliff:g> Sek."</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> Sek."</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> Sek."</string>
<string name="untitled" msgid="4638956954852782576">"<Unbenannt>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-System"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Privat"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Geschäftlich"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Kostenpflichtige Dienste"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Kostenpflichtige Aktionen"</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Ihre Nachrichten"</string>
@@ -723,8 +714,8 @@
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Ermöglicht der App das Abrufen, Überprüfen und Löschen von Benachrichtigungen, einschließlich Benachrichtigungen, die von anderen Apps gepostet wurden"</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"An Benachrichtigungs-Listener-Dienst binden"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Ermöglicht dem Inhaber, sich an die Oberfläche der obersten Ebene eines Benachrichtigungs-Listener-Dienstes zu binden. Sollte nie für normale Apps benötigt werden."</string>
- <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"An einen Bedingungsanbieterdienst binden"</string>
- <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Ermöglicht dem Inhaber, sich an die Oberfläche eines Bedingungsanbieterdienstes auf oberster Ebene zu binden. Für normale Apps sollte dies nie erforderlich sein."</string>
+ <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"An einen Bedingungsproviderdienst binden"</string>
+ <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Ermöglicht dem Inhaber, sich an die Oberfläche eines Bedingungsproviderdienstes auf oberster Ebene zu binden. Für normale Apps sollte dies nie erforderlich sein."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Vom Mobilfunkanbieter bereitgestellte Konfigurations-App aufrufen"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Ermöglicht dem Inhaber, die vom Mobilfunkanbieter bereitgestellte Konfigurations-App aufzurufen. Sollte für normale Apps nie benötigt werden."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Informationen zu den Netzwerkbedingungen erfassen"</string>
@@ -740,11 +731,11 @@
<string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Bildschirms überwachen und Telefon sperren oder alle Daten auf dem Telefon löschen, wenn zu häufig ein falsches Passwort eingegeben wird."</string>
<string name="policylab_resetPassword" msgid="2620077191242688955">"Passwort zum Entsperren des Bildschirms ändern"</string>
<string name="policydesc_resetPassword" msgid="605963962301904458">"Ändern Sie das Passwort zum Entsperren des Bildschirms."</string>
- <string name="policylab_forceLock" msgid="2274085384704248431">"Display sperren"</string>
+ <string name="policylab_forceLock" msgid="2274085384704248431">"Bildschirm sperren"</string>
<string name="policydesc_forceLock" msgid="1141797588403827138">"Legen Sie fest, wie und wann der Bildschirm gesperrt wird."</string>
<string name="policylab_wipeData" msgid="3910545446758639713">"Alle Daten löschen"</string>
<string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Auf Werkseinstellungen zurücksetzen und Daten auf dem Tablet ohne Warnung löschen"</string>
- <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Setzen Sie das Telefon auf Werkseinstellungen zurück. Dabei werden alle Daten ohne Warnung gelöscht."</string>
+ <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Setzen Sie das Telefon auf die Werkseinstellungen zurück. Dabei werden alle Daten ohne Warnung gelöscht."</string>
<string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Den globalen Proxy des Geräts festlegen"</string>
<string name="policydesc_setGlobalProxy" msgid="6387497466660154931">"Den bei aktivierter Richtlinie zu verwendenden globalen Proxy des Geräts festlegen. Nur der erste Geräteadministrator kann den gültigen globalen Proxy festlegen."</string>
<string name="policylab_expirePassword" msgid="885279151847254056">"Ablauf von Sperr-Passwort festlegen"</string>
@@ -1395,7 +1386,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Hintergrund"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Hintergrund ändern"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"Benachrichtigungs-Listener"</string>
- <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Bedingungsanbieter"</string>
+ <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Bedingungsprovider"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN aktiviert"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN wurde von <xliff:g id="APP">%s</xliff:g> aktiviert."</string>
<string name="vpn_text" msgid="3011306607126450322">"Zum Verwalten des Netzwerks berühren"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 9105cb2..296fd71 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> ημέρες"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> ημ. <xliff:g id="HOURS">%2$d</xliff:g> ώρες"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> ημ. <xliff:g id="HOURS">%2$d</xliff:g> ώρα"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ώρες"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ώρα <xliff:g id="MINUTES">%2$d</xliff:g> λ"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ώρα <xliff:g id="MINUTES">%2$d</xliff:g> λ"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> λεπτά"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> λ. <xliff:g id="SECONDS">%2$d</xliff:g> δευτ."</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> λ <xliff:g id="SECONDS">%2$d</xliff:g> δευτ."</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> δευτ."</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> δευτ."</string>
<string name="untitled" msgid="4638956954852782576">"<Χωρίς τίτλο>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Ασφαλής λειτουργία"</string>
<string name="android_system_label" msgid="6577375335728551336">"Σύστημα Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Προσωπικό"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Εργασία"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Υπηρεσίες επί πληρωμή"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Πραγματοποίηση ενεργειών για τις οποίες ενδέχεται να χρεωθείτε."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Τα μηνύματά σας"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 51a85e3..c4b7aa0 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> days"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> day <xliff:g id="HOURS">%2$d</xliff:g> hrs"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> day <xliff:g id="HOURS">%2$d</xliff:g> hr"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> hrs"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> hr <xliff:g id="MINUTES">%2$d</xliff:g> mins"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> hr <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> mins"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> secs"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sec"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> secs"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sec"</string>
<string name="untitled" msgid="4638956954852782576">"<Untitled>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Work"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services that cost you money"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Do things that can cost you money."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Your messages"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 51a85e3..c4b7aa0 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> days"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> day <xliff:g id="HOURS">%2$d</xliff:g> hrs"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> day <xliff:g id="HOURS">%2$d</xliff:g> hr"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> hrs"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> hr <xliff:g id="MINUTES">%2$d</xliff:g> mins"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> hr <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> mins"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> secs"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sec"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> secs"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sec"</string>
<string name="untitled" msgid="4638956954852782576">"<Untitled>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Work"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services that cost you money"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Do things that can cost you money."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Your messages"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 2a4f7e9..1225c81 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> días"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> día <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> día <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
<string name="untitled" msgid="4638956954852782576">"<Sin título>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Trabajo"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicios que te cuestan dinero"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Permite que las aplicaciones realicen actividades con cargo."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Tus mensajes"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 2e0d68b..1c6aa8d 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> días"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> día <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> día <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
<string name="untitled" msgid="4638956954852782576">"<Sin título>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"..."</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"> 999"</string>
<string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Trabajo"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicios por los que tienes que pagar"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Hacer acciones por las que puede que tengas que pagar"</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Tus mensajes"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 32abeb8..1c3d94a 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> päeva"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> päev <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> päev <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
<string name="untitled" msgid="4638956954852782576">"<Pealkirjata>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥."</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Turvarežiim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-süsteem"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Isiklik"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Töö"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Tasulised teenused"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Tasuliste toimingute tegemine."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Teie sõnumid"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index c5abcbd..dbc0d43 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"ترابایت"</string>
<string name="petabyteShort" msgid="5637816680144990219">"پتابایت"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> روز"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> روز و <xliff:g id="HOURS">%2$d</xliff:g> ساعت"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> روز و <xliff:g id="HOURS">%2$d</xliff:g> ساعت"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ساعت"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ساعت و <xliff:g id="MINUTES">%2$d</xliff:g> دقیقه"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ساعت و <xliff:g id="MINUTES">%2$d</xliff:g> دقیقه"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> دقیقه"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> دقیقه و <xliff:g id="SECONDS">%2$d</xliff:g> ثانیه"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> دقیقه و <xliff:g id="SECONDS">%2$d</xliff:g> ثانیه"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> ثانیه"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> ثانیه"</string>
<string name="untitled" msgid="4638956954852782576">"<بدون عنوان>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"بیشتر از 999"</string>
<string name="safeMode" msgid="2788228061547930246">"حالت ایمن"</string>
<string name="android_system_label" msgid="6577375335728551336">"سیستم Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"شخصی"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"محل کار"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"سرویسهای غیر رایگان"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"انجام کارهایی که برای شما هزینه دارد."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"پیامهای شما"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 945c7ab..03dfb12 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"Tt"</string>
<string name="petabyteShort" msgid="5637816680144990219">"Pt"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> päivää"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> päivä <xliff:g id="HOURS">%2$d</xliff:g> t"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> päivä <xliff:g id="HOURS">%2$d</xliff:g> t"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> t"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> t <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> t <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
<string name="untitled" msgid="4638956954852782576">"<Nimetön>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -199,6 +188,10 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Suojattu tila"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string>
+ <!-- no translation found for user_owner_label (2804351898001038951) -->
+ <skip />
+ <!-- no translation found for managed_profile_label (6260850669674791528) -->
+ <skip />
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Maksulliset palvelut"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Suorita mahdollisesti maksullisia toimintoja."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Omat viestit"</string>
@@ -409,10 +402,8 @@
<string name="permdesc_bindVpnService" msgid="2067845564581693905">"Antaa sovelluksen sitoutua VPN-palvelun ylemmän tason käyttöliittymään. Ei tavallisten sovellusten käyttöön."</string>
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"sido taustakuvaan"</string>
<string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Antaa sovelluksen sitoutua taustakuvan ylätason käyttöliittymään. Ei tavallisten sovellusten käyttöön."</string>
- <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
- <skip />
- <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
- <skip />
+ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"puheohjauspalveluun sitominen"</string>
+ <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Antaa sovelluksen luoda sidoksen puheohjauspalvelun ylätason rajapintaan. Ei tavallisten sovelluksien käyttöön."</string>
<string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"etänäyttöön sitoutuminen"</string>
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Antaa sovelluksen sitoutua etänäytön ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"sitoudu widget-palveluun"</string>
@@ -725,10 +716,8 @@
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Antaa sovelluksen noutaa, tutkia ja tyhjentää ilmoituksia (myös muiden sovelluksien lähettämiä)."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"sido ilmoituskuuntelijapalveluun"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Antaa sovelluksen sitoutua ilmoituskuuntelijan ylimmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
- <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
- <skip />
- <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
- <skip />
+ <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"ehtojen toimituspalveluun sitominen"</string>
+ <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Antaa sovelluksen luoda sidoksen ehtojen toimituspalvelun ylätason rajapintaan. Ei tavallisten sovelluksien käyttöön."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Palveluntarjoajan määrityssovelluksen käynnistäminen"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Antaa luvanhaltijan käynnistää palveluntarjoajan määrityssovelluksen. Ei tavallisten sovelluksien käyttöön."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"verkon tilahavaintojen kuunteleminen"</string>
@@ -1399,8 +1388,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Taustakuva"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Vaihda taustakuvaa"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"Ilmoituskuuntelija"</string>
- <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
- <skip />
+ <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Ehtojen toimituspalvelu"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN on aktivoitu"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> on aktivoinut VPN-yhteyden"</string>
<string name="vpn_text" msgid="3011306607126450322">"Voit hallinnoida verkkoa koskettamalla."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index c917749..276be79 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"To"</string>
<string name="petabyteShort" msgid="5637816680144990219">"Po"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> jours"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> j et <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> j et <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h et <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h et <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min et <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min et <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
<string name="untitled" msgid="4638956954852782576">"<Sans_titre>"</string>
<string name="ellipsis" msgid="7899829516048813237">"..."</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">">999"</string>
<string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
<string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Personnel"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Travail"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services payants"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Effectuer des opérations payantes"</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Vos messages"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 9359606..6a6ed88 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"To"</string>
<string name="petabyteShort" msgid="5637816680144990219">"Po"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> jours"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> j et <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> j et <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h et <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h et <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min et <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min et <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
<string name="untitled" msgid="4638956954852782576">"<Sans nom>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">">999"</string>
<string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
<string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Personnel"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Professionnel"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services payants"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Effectuer des opérations payantes"</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Vos messages"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 3d5f4df..957e76a 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> दिन"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> दिन <xliff:g id="HOURS">%2$d</xliff:g> घंटे"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> दिन <xliff:g id="HOURS">%2$d</xliff:g> घंटा"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> घंटे"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> घं. <xliff:g id="MINUTES">%2$d</xliff:g> मि."</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> घं. <xliff:g id="MINUTES">%2$d</xliff:g> मि."</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> मिनट"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> मि. <xliff:g id="SECONDS">%2$d</xliff:g> से."</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> मि. <xliff:g id="SECONDS">%2$d</xliff:g> से."</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> सेकंड"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> सेकंड"</string>
<string name="untitled" msgid="4638956954852782576">"<शीर्षक-रहित>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android सिस्टम"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"व्यक्तिगत"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"कार्यालय"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"वे सेवाएं जिन पर आप खर्चा करते हैं"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"ऐसे कार्य करें जिससे आपका धन खर्च हो सकता है."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"आपके संदेश"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index a195512..e4db3e6 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> d"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> d <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> d <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
<string name="untitled" msgid="4638956954852782576">"<Bez naslova>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sustav Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Osobno"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Posao"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Usluge koje se plaćaju"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Radite stvari koje će uzrokovati novčane troškove."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Vaše poruke"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 6e82bb8..6130c5e 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> nap"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> nap <xliff:g id="HOURS">%2$d</xliff:g> óra"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> nap <xliff:g id="HOURS">%2$d</xliff:g> óra"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> óra"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> óra <xliff:g id="MINUTES">%2$d</xliff:g> perc"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> óra <xliff:g id="MINUTES">%2$d</xliff:g> perc"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> perc"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> perc <xliff:g id="SECONDS">%2$d</xliff:g> mp"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> perc <xliff:g id="SECONDS">%2$d</xliff:g> mp"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> másodperc"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> másodperc"</string>
<string name="untitled" msgid="4638956954852782576">"<Névtelen>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Biztonsági üzemmód"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android rendszer"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Személyes"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Munkahelyi"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Fizetős szolgáltatások"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Olyan dolgok végrehajtása, amelyek pénzbe kerülnek."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Saját üzenetek"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 12e5fdb..a4a5f48 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"Տբ"</string>
<string name="petabyteShort" msgid="5637816680144990219">"Պբ"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> օր"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> օր <xliff:g id="HOURS">%2$d</xliff:g> ժ"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> օր <xliff:g id="HOURS">%2$d</xliff:g> ժ"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ժ"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ժ <xliff:g id="MINUTES">%2$d</xliff:g> ր"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ժ <xliff:g id="MINUTES">%2$d</xliff:g> ր"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> րոպե"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> ր <xliff:g id="SECONDS">%2$d</xliff:g> վ"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> ր <xliff:g id="SECONDS">%2$d</xliff:g> վ"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> վ"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> վ"</string>
<string name="untitled" msgid="4638956954852782576">"<Անանուն>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Անվտանգ ռեժիմ"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android համակարգ"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Անձնական"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Աշխատանքային"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Ծառայություններ, որոնց համար կգանձվեք"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Կատարել գործողություններ, որի դիմաց ձեր հաշվից գումար կծախսվի:"</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Ձեր հաղորդագրությունները"</string>
@@ -409,10 +400,8 @@
<string name="permdesc_bindVpnService" msgid="2067845564581693905">"Թույլ է տալիս սեփականատիրոջը միանալ Vpn ծառայության վերին մակարդակի ինտերֆեյսին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"միանալ պաստառին"</string>
<string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Թույլ է տալիս սեփականատիրոջը միանալ պաստառի վերին մակարդակի ինտերֆեյսին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
- <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
- <skip />
- <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
- <skip />
+ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"կապվել ձայնային փոխազդիչին"</string>
+ <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Թույլ է տալիս սեփականատիրոջը միանալ ձայնային փոխազդիչի բազային միջերեսին: Սովորական ծրագրերի համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
<string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"միանալ հեռակա էկրանին"</string>
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Թույլ է տալիս սեփականատիրոջը միանալ հեռակա էկրանի վերին մակարդակի ինտերֆեյսին: Սովորական ծրագրերի համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"միանալ վիջեթ ծառայությանը"</string>
@@ -725,10 +714,8 @@
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Թույլ է տալիս հավելվածին առբերել, ուսումնասիրել և մաքրել ծանուցումներն, այդ թվում նաև այլ հավելվածների կողմից գրառվածները:"</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"միանալ ծանուցումների ունկնդրիչ ծառայությանը"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Թույլ է տալիս սեփականատիրոջը միանալ ծանուցումները ունկնդրող ծառայության վերին մակարդակի ինտերֆեյսին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
- <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
- <skip />
- <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
- <skip />
+ <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"կապվել պայմանների մատակարարի ծառայությանը"</string>
+ <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Թույլ է տալիս սեփականատիրոջը միանալ պայմանների մատակարարների բազային միջերեսին: Սովորական ծրագրերի համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"գործարկել օպերատորի կողմից տրամադրված կազմաձևման ծրագիրը"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Թույլ է տալիս սեփականատիրոջը գործարկել օպերատորի կողմից տրամադրված կազմաձևման ծրագիրը: Սովորական ծրագրերի համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"լսել դիտարկումներ ցանցային պայմանների վերաբերյալ"</string>
@@ -1399,8 +1386,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Պաստառ"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Փոխել պաստառը"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"Ծանուցման ունկնդիր"</string>
- <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
- <skip />
+ <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Պայմանների մատակարար"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN-ը ակտիվացված է"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN-ն ակտիվացված է <xliff:g id="APP">%s</xliff:g>-ի կողմից"</string>
<string name="vpn_text" msgid="3011306607126450322">"Հպեք` ցանցի կառավարման համար:"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 2fb00bb..6003a23 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> hari"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> hari <xliff:g id="HOURS">%2$d</xliff:g> jam"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> hari <xliff:g id="HOURS">%2$d</xliff:g> jam"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> jam"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> jam <xliff:g id="MINUTES">%2$d</xliff:g> mnt"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> jam <xliff:g id="MINUTES">%2$d</xliff:g> mnt"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> mnt"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> mnt <xliff:g id="SECONDS">%2$d</xliff:g> dtk"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> mnt <xliff:g id="SECONDS">%2$d</xliff:g> dtk"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> dtk"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> dtk"</string>
<string name="untitled" msgid="4638956954852782576">"<Tanpa judul>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Mode aman"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Pribadi"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Kantor"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Layanan berbayar"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Lakukan hal yang dapat dikenai biaya."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Pesan Anda"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index af8ed3f..0e83a2f 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> giorni"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> giorno <xliff:g id="HOURS">%2$d</xliff:g> ore"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> giorno <xliff:g id="HOURS">%2$d</xliff:g> ora"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ore"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ora <xliff:g id="MINUTES">%2$d</xliff:g> minuti"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ora <xliff:g id="MINUTES">%2$d</xliff:g> minuto"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> minuti"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> minuto <xliff:g id="SECONDS">%2$d</xliff:g> secondi"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> minuto <xliff:g id="SECONDS">%2$d</xliff:g> secondo"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> secondi"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> secondo"</string>
<string name="untitled" msgid="4638956954852782576">"<Senza nome>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Modalità provvisoria"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Personale"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Lavoro"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servizi che prevedono un costo"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Svolgono operazioni che possono comportare un costo."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"I tuoi messaggi"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 0157f74..8002d3a 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> ימים"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"יום <xliff:g id="DAYS">%1$d</xliff:g> <xliff:g id="HOURS">%2$d</xliff:g> שע\'"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"יום <xliff:g id="DAYS">%1$d</xliff:g> שעה <xliff:g id="HOURS">%2$d</xliff:g>"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> שעות"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"שעה <xliff:g id="HOURS">%1$d</xliff:g> <xliff:g id="MINUTES">%2$d</xliff:g> דק\'"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> שעות <xliff:g id="MINUTES">%2$d</xliff:g> דק\'"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> דקות"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"דקה <xliff:g id="MINUTES">%1$d</xliff:g> <xliff:g id="SECONDS">%2$d</xliff:g> שנ\'"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"דקה <xliff:g id="MINUTES">%1$d</xliff:g> שנ\' <xliff:g id="SECONDS">%2$d</xliff:g>"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> שניות"</string>
+ <string name="durationSecond" msgid="985669622276420331">"שנייה <xliff:g id="SECONDS">%1$d</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">">ללא כותרת<"</string>
<string name="ellipsis" msgid="7899829516048813237">"..."</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"מצב בטוח"</string>
<string name="android_system_label" msgid="6577375335728551336">"מערכת Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"אישי"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"עבודה"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"שירותים שעולים כסף"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"ביצוע פעולות שעשויות לעלות לך כסף."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"ההודעות שלך"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index a9c5cfb..704b935 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g>日"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g>日<xliff:g id="HOURS">%2$d</xliff:g>時間"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g>日<xliff:g id="HOURS">%2$d</xliff:g>時間"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g>時間"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g>時間<xliff:g id="MINUTES">%2$d</xliff:g>分"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g>時間<xliff:g id="MINUTES">%2$d</xliff:g>分"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g>分"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g>分<xliff:g id="SECONDS">%2$d</xliff:g>秒"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g>分<xliff:g id="SECONDS">%2$d</xliff:g>秒"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g>秒"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g>秒"</string>
<string name="untitled" msgid="4638956954852782576">"<新規>"</string>
<string name="ellipsis" msgid="7899829516048813237">"..."</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"セーフモード"</string>
<string name="android_system_label" msgid="6577375335728551336">"Androidシステム"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"プライベート"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"職場"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"料金の発生するサービス"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"料金発生の可能性がある操作を実行します。"</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"送受信したメッセージ"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index e5ec81b..0c179c0 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"ტბაიტი"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> დღე"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> დღე <xliff:g id="HOURS">%2$d</xliff:g> სთ"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> დღე <xliff:g id="HOURS">%2$d</xliff:g> სთ"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> სთ"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> სთ <xliff:g id="MINUTES">%2$d</xliff:g> წთ"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> სთ <xliff:g id="MINUTES">%2$d</xliff:g> წთ"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> წთ"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> წთ <xliff:g id="SECONDS">%2$d</xliff:g> წმ"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> წთ <xliff:g id="SECONDS">%2$d</xliff:g> წმ"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> წმ"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> წმ"</string>
<string name="untitled" msgid="4638956954852782576">"უსათაურო"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"უსაფრთხო რეჟიმი"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-ის სისტემა"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"პირადი"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"სამსახური"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"სერვისები, რომელშიც ფულის გადახდა გიწევთ"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"ისეთი აქტივობების განხორციელება, რომლებშიც ფულის გადახდა მოგიწევთ."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"თქვენი შეტყობინებები"</string>
@@ -409,10 +400,8 @@
<string name="permdesc_bindVpnService" msgid="2067845564581693905">"აპს შეეძლება Vpn სერვისის ზედა დონის ინტერფეისთან დაკავშირება. არასდროს გამოიყენება ჩვეულებრივ აპებში."</string>
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"ფონზე მიჭედება"</string>
<string name="permdesc_bindWallpaper" msgid="7108428692595491668">"მფლობელს შეეძლება ფონის ზედა დონის ინტერფეისთან დაკავშირება. არასდროს გამოიყენება ჩვეულებრივ აპებში."</string>
- <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
- <skip />
- <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
- <skip />
+ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"ხმის ინტერაქტორთან შეკავშირება"</string>
+ <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"მფლობელს შეეძლება შეკავშირდეს ხმის ინტერაქციის სერვისების ზედა დონის ინტერფეისთან. ჩვეულებრივ აპს ეს წესით არასოდეს უნდა დასჭირდეს."</string>
<string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"დისტანციურ მონიტორზე მიბმა"</string>
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"მფლობელს შეეძლება მიებას დისტანციურ მონიტორის ზედა დონის ინტერფეისს. ჩვეულებრივ აპს ეს წესით არასოდეს უნდა დაჭირდეს."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ვიჯეტ სერვისთან დაკავშირება"</string>
@@ -725,10 +714,8 @@
<string name="permdesc_accessNotifications" msgid="458457742683431387">"აპს შეეძლება მოიძიოს, გამოიკვლიოს და წაშალოს შეტყობინებები, მათ შორის სხვა აპების მიერ გამოქვეყნებული."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"შეტყობინებების მოსმენის სერვისთან დაკავშირება"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"მფლობელს შეეძლება შეტყობინებების მსმენლის სერვისის ზედა დონის ინტერფეისთან დაკავშირება. არ უნდა მოხდეს მისი გამოყენება ჩვეუელებრივი აპებისთვის.ფ"</string>
- <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
- <skip />
- <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
- <skip />
+ <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"მდგომარეობის პროვაიდერის სერვისებთან შეკავშირება"</string>
+ <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"მფლობელს შეეძლება შეკავშირდეს მდგომარეობის პროვაიდერის სერვისების ზედა დონის ინტერფეისთან. ჩვეულებრივ აპს ეს წესით არასოდეს უნდა დასჭირდეს."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ოპერატორის მიერ მოწოდებული კოფიგურაციის აპის გამოხმობა"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"საშუალებას აძლევს მფლობელს გამოიწვიოს ოპერატორის მიერ მოწოდებული კონფიგურაციის აპი. ჩვეულებრივ აპს ეს წესით არასოდეს არ უნდა დაჭირდეს."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"განხორციელდეს ქსელის მდგომარეობის მონიტორინგი"</string>
@@ -1399,8 +1386,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"ფონი"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"ფონის შეცვლა"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"შეტყობინებების მსმენელი"</string>
- <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
- <skip />
+ <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"მდგომარეობის პროვაიდერი"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN გააქტიურებულია"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN გააქტიურებულია <xliff:g id="APP">%s</xliff:g>-ის მიერ"</string>
<string name="vpn_text" msgid="3011306607126450322">"შეეხეთ ქსელის სამართავად."</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index e9a021c..4d6f0a3 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"តេរ៉ាបៃ"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> ថ្ងៃ"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> ថ្ងៃ <xliff:g id="HOURS">%2$d</xliff:g> ម៉ោង"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> ថ្ងៃ <xliff:g id="HOURS">%2$d</xliff:g> ម៉ោង"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ម៉ោង"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ម៉ោង <xliff:g id="MINUTES">%2$d</xliff:g> នាទី"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ម៉ោង <xliff:g id="MINUTES">%2$d</xliff:g> នាទី"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> នាទី"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g>នាទី <xliff:g id="SECONDS">%2$d</xliff:g>វិនាទី"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g>នាទី <xliff:g id="SECONDS">%2$d</xliff:g>វិនាទី"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> វិនាទី"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> វិនាទី"</string>
<string name="untitled" msgid="4638956954852782576">"<គ្មានចំណងជើង>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"របៀបសុវត្ថិភាព"</string>
<string name="android_system_label" msgid="6577375335728551336">"ប្រព័ន្ធ Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"ផ្ទាល់ខ្លួន"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"កន្លែងធ្វើការ"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"សេវាកម្មដែលកាត់លុយរបស់អ្នក"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"ធ្វើអ្វីដែលអាចកាត់លុយរបស់អ្នក។"</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"សាររបស់អ្នក"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 7c6feba..310b1f0 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g>일"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g>일 <xliff:g id="HOURS">%2$d</xliff:g>시간"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g>일 <xliff:g id="HOURS">%2$d</xliff:g>시간"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g>시간"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g>시간 <xliff:g id="MINUTES">%2$d</xliff:g>분"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g>시간 <xliff:g id="MINUTES">%2$d</xliff:g>분"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g>분"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g>분 <xliff:g id="SECONDS">%2$d</xliff:g>초"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g>분 <xliff:g id="SECONDS">%2$d</xliff:g>초"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g>초"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g>초"</string>
<string name="untitled" msgid="4638956954852782576">"<제목 없음>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"안전 모드"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 시스템"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"개인"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"직장"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"요금이 부과되는 서비스"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"요금이 부과될 수 있는 작업을 수행할 수 있도록 합니다."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"메시지"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index b31fbff..08ba7e1 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> ມື້"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> ມື້ <xliff:g id="HOURS">%2$d</xliff:g> ຊມ"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> ມື້ <xliff:g id="HOURS">%2$d</xliff:g> ຊມ"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ຊມ"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ຊມ <xliff:g id="MINUTES">%2$d</xliff:g> ນທ"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ຊມ <xliff:g id="MINUTES">%2$d</xliff:g> ນທ"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> ນທ"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> ນທ <xliff:g id="SECONDS">%2$d</xliff:g> ວິ"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> ນທ <xliff:g id="SECONDS">%2$d</xliff:g> ວິ"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> ວິ"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> ວິ"</string>
<string name="untitled" msgid="4638956954852782576">"<ບໍ່ມີຊື່>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"ລະບົບ Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"ສ່ວນໂຕ"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"ບ່ອນເຮັດວຽກ"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"ບໍລິການທີ່ເຮັດໃຫ້ທ່ານເສຍເງິນ"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"ເຮັດສິ່ງທີ່ທ່ານຕ້ອງເສຍຄ່າໃຊ້ຈ່າຍ."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"ຂໍ້ຄວາມຂອງທ່ານ"</string>
@@ -409,10 +400,8 @@
<string name="permdesc_bindVpnService" msgid="2067845564581693905">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງເຊື່ອມໂຍງກັບສ່ວນຕິດຕໍ່ລະດັບເທິງສຸດ ຂອງບໍລິການ VPN. ແອັບຯທົ່ວໄປບໍ່ຄວນຈຳເປັນຕ້ອງໃຊ້."</string>
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"ເຊື່ອມໂຍງກັບພາບພື້ນຫຼັງ"</string>
<string name="permdesc_bindWallpaper" msgid="7108428692595491668">"ອະນຸຍາດໃຫ້ຜູ່ໃຊ້ເຊື່ອມໂຍງກັບສ່ວນຕິດຕໍ່ລະດັບສູງສຸດ ຂອງພາບພື້ນຫຼັງໃດນຶ່ງ. ແອັບຯທຳມະດາບໍ່ຄວນຈຳເປັນຕ້ອງໃຊ້."</string>
- <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
- <skip />
- <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
- <skip />
+ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"ເຊື່ອມໂຍງກັບຕົວຕິດຕໍ່ດ້ວຍສຽງ"</string>
+ <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງເຊື່ອມໂຍງສ່ວນຕິດຕໍ່ລະດັບສູງສຸດຂອງບໍລິການການຕິດຕໍ່ດ້ວຍສຽງ."</string>
<string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ຜູກກັນເພື່ອສະແດງຜົນທາງໄກ."</string>
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"ອະນຸຍາດໃຫ້ຜູ່ຖືຜູກກັບສ່ວນຕິດຕໍ່ລະດັບສູງສຸດ ຂອງການສະແດງຜົນທາງໄກ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ເຊື່ອມໂຍງໄປຫາບໍລິການວິດເຈັດ"</string>
@@ -725,10 +714,8 @@
<string name="permdesc_accessNotifications" msgid="458457742683431387">"ອະນຸຍາດໃຫ້ແອັບຯດຶງຂໍ້ມູນ, ກວດສອບ ແລະລຶບລ້າງການແຈ້ງເຕືອນ ຮວມທັງພວກທີ່ໂພສໂດຍແອັບຯອື່ນໆນຳ."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"ເຊື່ອມໂຍງກັບບໍລິການໂຕຟັງການແຈ້ງເຕືອນ"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງເຊື່ອມໂຍງສ່ວນຕິດຕໍ່ລະດັບເທິງສຸດ ຂອງຜູ່ຟັງບໍລິການການແຈ້ງເຕືອນ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
- <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
- <skip />
- <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
- <skip />
+ <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"ເຊື່ອມໂຍງກັບບໍລິການຜູ່ສະໜອງເງື່ອນໄຂ"</string>
+ <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງເຊື່ອມໂຍງສ່ວນຕິດຕໍ່ລະດັບສູງສຸດຂອງບໍລິການສະໜອງເງື່ອນໄຂ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ຮ້ອງຂໍແອັບຯປັບຄ່າທີ່ສະໜອງໂດຍຜູ່ໃຫ້ບໍລິການ"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງຮ້ອງຂໍແອັບຯປັບຄ່າທີ່ສະໜອງໂດຍຜູ່ໃຫ້ບໍລິການ. ບໍ່ໜ້າຈະຕ້ອງການສຳລັບແອັບຯທົ່ວໄປ."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ຕິດຕາມເພື່ອສັງເກດສະພາບຂອງເຄືອຂ່າຍ"</string>
@@ -1399,8 +1386,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"ພາບພື້ນຫຼັງ"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"ປ່ຽນພາບພື້ນຫຼັງ"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"ໂຕຟັງການແຈ້ງເຕືອນ"</string>
- <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
- <skip />
+ <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ຜູ່ສະໜອງເງື່ອນໄຂ"</string>
<string name="vpn_title" msgid="19615213552042827">"ເປີດນຳໃຊ້ VPN ແລ້ວ"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"ເປີດໃຊ້ VPN ໂດຍ <xliff:g id="APP">%s</xliff:g>"</string>
<string name="vpn_text" msgid="3011306607126450322">"ແຕະເພື່ອຈັດການເຄືອຂ່າຍ."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 62b6c7a..7250f02 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> d."</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> d. <xliff:g id="HOURS">%2$d</xliff:g> val."</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> d. <xliff:g id="HOURS">%2$d</xliff:g> val."</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> val."</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> val. <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> val. <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min."</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> sek."</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> sek."</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sek."</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sek."</string>
<string name="untitled" msgid="4638956954852782576">"<Be pavadinimo>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Saugos režimas"</string>
<string name="android_system_label" msgid="6577375335728551336">"„Android“ sistema"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Asmeninė"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Darbo"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Paslaugos, už kurias mokėjote"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Atlikite mokamus veiksmus."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Jūsų pranešimai"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index b803e61..4c48278 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> d."</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> d. <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> d. <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
<string name="untitled" msgid="4638956954852782576">"<Bez nosaukuma>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"Pārsniedz"</string>
<string name="safeMode" msgid="2788228061547930246">"Drošais režīms"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android sistēma"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Personisks"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Darba"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Maksas pakalpojumi"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Veikt darbības, par kurām, iespējams, būs jāmaksā."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Jūsu ziņojumi"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index cc0fa7f..c609745 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TБ"</string>
<string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> өдөр"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> өдөр <xliff:g id="HOURS">%2$d</xliff:g> цаг"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> өдөр <xliff:g id="HOURS">%2$d</xliff:g> цаг"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> цаг"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> цаг <xliff:g id="MINUTES">%2$d</xliff:g> минут"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> цаг <xliff:g id="MINUTES">%2$d</xliff:g> мин"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> мин"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> мин <xliff:g id="SECONDS">%2$d</xliff:g> секунд"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> мин <xliff:g id="SECONDS">%2$d</xliff:g> сек"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> сек"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> сек"</string>
<string name="untitled" msgid="4638956954852782576">"<Гарчиггүй>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Аюулгүй горим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Андройд систем"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Хувийн"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Ажил"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Танаас төлбөр авдаг үйлчилгээнүүд"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Таны төлбөрт оруулах зүйлийг хийх."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Таны мессеж"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 53c9b94..ea9ffb3 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> hari"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> hari <xliff:g id="HOURS">%2$d</xliff:g> jam"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> hari <xliff:g id="HOURS">%2$d</xliff:g> jam"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> jam"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> jam <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> jam <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> minit"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> saat"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> saat"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> saat"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> saat"</string>
<string name="untitled" msgid="4638956954852782576">"<Tidak bertajuk>"</string>
<string name="ellipsis" msgid="7899829516048813237">"..."</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,10 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Mod selamat"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
+ <!-- no translation found for user_owner_label (2804351898001038951) -->
+ <skip />
+ <!-- no translation found for managed_profile_label (6260850669674791528) -->
+ <skip />
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Perkhidmatan yang anda perlu bayar"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Melakukan perkara yang boleh mengenakan bayaran kepada anda."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Mesej anda"</string>
@@ -409,10 +402,8 @@
<string name="permdesc_bindVpnService" msgid="2067845564581693905">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan Vpn. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"terikat pada kertas dinding"</string>
<string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi kertas dinding. Tidak sekali-kali diperlukan untuk apl biasa."</string>
- <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
- <skip />
- <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
- <skip />
+ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"terikat kepada interaksi suara"</string>
+ <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan interaksi suara. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"terikat kepada paparan jauh"</string>
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi paparan jauh. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"terikat kepada perkhidmatan widget"</string>
@@ -725,10 +716,8 @@
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Membenarkan apl untuk mendapatkan semula, memeriksa dan memadam bersih pemberitahuan, termasuk yang disiarkan oleh apl lain."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"ikat kepada perkhidmatan pendengar pemberitahuan"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan pendengar pemberitahuan. Tidak sekali-kali diperlukan untuk apl biasa."</string>
- <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
- <skip />
- <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
- <skip />
+ <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"terikat kepada perkhidmatan pembekal keadaan"</string>
+ <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan pembekal keadaan. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"gunakan apl konfigurasi yang disediakan oleh pembawa"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Membenarkan pemegang menggunakan apl konfigurasi yang diberikan oleh pembawa. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"dengar pemerhatian mengenai keadaan rangkaian"</string>
@@ -1399,8 +1388,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Kertas dinding"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Tukar kertas dinding"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"Pendengar pemberitahuan"</string>
- <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
- <skip />
+ <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Pembekal keadaan"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN diaktifkan"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
<string name="vpn_text" msgid="3011306607126450322">"Sentuh untuk mengurus rangkaian."</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index a67cb28..16c5352 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dager"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> t"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> t"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> t"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> t <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> t <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sek"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sek"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sek"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sek"</string>
<string name="untitled" msgid="4638956954852782576">"<Uten navn>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Sikkermodus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Personlig"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Jobb"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Betaltjenester"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Gjøre ting som kan koste deg penger."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Meldinger"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 3b2391f..c19adf2 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dagen"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> uur"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> uur"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> uur"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> uur <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> uur <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> minuten"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sec"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sec"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> seconden"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> seconde"</string>
<string name="untitled" msgid="4638956954852782576">"<Zonder titel>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
<string name="safeMode" msgid="2788228061547930246">"Veilige modus"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-systeem"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Persoonlijk"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Werk"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Services waarvoor u moet betalen"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Activiteiten uitvoeren waarvoor kosten in rekening kunnen worden gebracht."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Uw berichten"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index b80c1fd..949fea8 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dni"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dzień <xliff:g id="HOURS">%2$d</xliff:g> godz."</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dzień <xliff:g id="HOURS">%2$d</xliff:g> godz."</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> godz."</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> godz. <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> godz. <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
<string name="untitled" msgid="4638956954852782576">"<Bez nazwy>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">">999"</string>
<string name="safeMode" msgid="2788228061547930246">"Tryb awaryjny"</string>
<string name="android_system_label" msgid="6577375335728551336">"System Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Osobiste"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Praca"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Usługi płatne"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Wykonywanie czynności, za które pobierana jest opłata."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Twoje wiadomości"</string>
@@ -737,7 +728,7 @@
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolowanie długości haseł odblokowania ekranu i dozwolonych w nich znaków"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitoruj próby odblokowania ekranu"</string>
<string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Przy odblokowywaniu ekranu monitoruj, ile razy wpisano nieprawidłowe hasło i blokuj tablet lub usuń z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy."</string>
- <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Przy odblokowywaniu ekranu monitoruje, ile razy wpisano nieprawidłowe hasło i blokuje telefon lub usuwa z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy."</string>
+ <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Przy odblokowywaniu ekranu monitoruje, ile razy wpisano nieprawidłowe hasło, i blokuje telefon lub usuwa z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy"</string>
<string name="policylab_resetPassword" msgid="2620077191242688955">"Zmień hasło odblokowania ekranu"</string>
<string name="policydesc_resetPassword" msgid="605963962301904458">"Zmienianie hasła odblokowania ekranu"</string>
<string name="policylab_forceLock" msgid="2274085384704248431">"Zablokuj ekran"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 668f9ef..ecec099 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dias"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dia <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dia <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> horas"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min."</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> seg."</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> seg."</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> seg."</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> seg."</string>
<string name="untitled" msgid="4638956954852782576">"<Sem nome>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Pessoal"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Trabalho"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serviços que implicam pagamento"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Efetuar ações que implicam pagamento."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"As suas mensagens"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index db493e0..93107ca 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dias"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dia <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dia <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> horas"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
<string name="untitled" msgid="4638956954852782576">"<Sem título>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -199,6 +188,10 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">">999"</string>
<string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
+ <!-- no translation found for user_owner_label (2804351898001038951) -->
+ <skip />
+ <!-- no translation found for managed_profile_label (6260850669674791528) -->
+ <skip />
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Serviços que geram gastos"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Faça coisas que podem custar dinheiro."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Suas mensagens"</string>
@@ -409,10 +402,8 @@
<string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite que seu proprietário sujeite a interface de alto nível de um serviço de VPN. Nunca deve ser necessário para aplicativos normais."</string>
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"sujeitar-se a um plano de fundo"</string>
<string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite que o proprietário utilize interface de nível superior de um plano de fundo. Nunca deve ser necessário para aplicativos normais."</string>
- <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
- <skip />
- <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
- <skip />
+ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"associar a um interagente de voz"</string>
+ <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permite que o proprietário use a interface de nível superior de um serviço de interação de voz. Não deve ser necessário para aplicativos comuns."</string>
<string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"usar uma tela remota"</string>
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite que o proprietário use a interface de nível superior de uma tela remota. Não deve ser necessário para aplicativos comuns."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"sujeitar-se a um serviço de widget"</string>
@@ -725,10 +716,8 @@
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que o aplicativo recupere, examine e limpe notificações, inclusive as postadas por outros aplicativos."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"sujeitar a um serviço ouvinte de notificações"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite que o proprietário sujeite a interface de nível superior a um serviço ouvinte de notificações. Não deve ser necessário para aplicativos comuns."</string>
- <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
- <skip />
- <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
- <skip />
+ <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"associar a um serviço provedor de condições"</string>
+ <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permite que o proprietário use a interface de nível superior de um serviço provedor de condições. Não deve ser necessário para aplicativos comuns."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invocar o aplicativo de configuração fornecido pela operadora"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite que o proprietário invoque o aplicativo de configuração fornecido pela operadora. Não deve ser necessário para aplicativos comuns."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"detectar observações nas condições da rede"</string>
@@ -1399,8 +1388,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Plano de fundo"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar plano de fundo"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"Ouvinte de notificações"</string>
- <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
- <skip />
+ <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provedor de condições"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN ativada"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"A VPN está ativada por <xliff:g id="APP">%s</xliff:g>"</string>
<string name="vpn_text" msgid="3011306607126450322">"Toque para gerenciar a rede."</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 3103b1f..6bdaee5 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -246,6 +246,10 @@
<skip />
<string name="safeMode" msgid="2788228061547930246">"Modus segirà"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
+ <!-- no translation found for user_owner_label (2804351898001038951) -->
+ <skip />
+ <!-- no translation found for managed_profile_label (6260850669674791528) -->
+ <skip />
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servetschs che custan"</string>
<!-- no translation found for permgroupdesc_costMoney (3293301903409869495) -->
<skip />
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 3ee0b8a..568e093 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TO"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PO"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> (de) zile"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> zile <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> zi <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> (de) min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sec"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sec"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sec"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sec"</string>
<string name="untitled" msgid="4638956954852782576">"<Fără titlu>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,10 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"˃999"</string>
<string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistemul Android"</string>
+ <!-- no translation found for user_owner_label (2804351898001038951) -->
+ <skip />
+ <!-- no translation found for managed_profile_label (6260850669674791528) -->
+ <skip />
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Servicii cu plată"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Efectuează acţiuni care sunt cu plată."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Mesajele dvs."</string>
@@ -409,10 +402,8 @@
<string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unui serviciu VPN. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"conectare la o imagine de fundal"</string>
<string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unei imagini de fundal. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
- <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
- <skip />
- <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
- <skip />
+ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"conectare la un serviciu de interacțiune vocală"</string>
+ <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permite proprietarului să se conecteze la interfața de nivel superior a unui serviciu de interacțiune vocală. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
<string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"conectare la un ecran la distanță"</string>
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite proprietarului să se conecteze la interfața de nivel superior a unui ecran la distanță. Nu ar trebui să fie niciodată necesară pentru aplicațiile obișnuite."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"conectare la un serviciu widget"</string>
@@ -725,10 +716,8 @@
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite aplicației să recupereze, să examineze și să șteargă notificări, inclusiv pe cele postate de alte aplicații."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"conectare la un serviciu de citire a notificărilor"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite proprietarului să se conecteze la interfața de nivel superior a unui serviciu de citire a notificărilor. În mod normal aplicațiile nu ar trebui să aibă nevoie de această permisiune."</string>
- <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
- <skip />
- <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
- <skip />
+ <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"conectare la un serviciu furnizor de condiții"</string>
+ <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permite proprietarului să se conecteze la interfața de nivel superior a unui serviciu furnizor de condiții. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"apelarea aplicației de configurare furnizată de operator"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite proprietarului să apeleze aplicația de configurare furnizată de operator. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ascultă observații despre starea rețelei"</string>
@@ -1399,8 +1388,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Imagine de fundal"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Modificaţi imaginea de fundal"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"Serviciu de citire a notificărilor"</string>
- <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
- <skip />
+ <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Furnizor de condiții"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN activat"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN este activată de <xliff:g id="APP">%s</xliff:g>"</string>
<string name="vpn_text" msgid="3011306607126450322">"Atingeţi pentru a gestiona reţeaua."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 8c7a566..8a0141a 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TБ"</string>
<string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> дн."</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> день <xliff:g id="HOURS">%2$d</xliff:g> ч."</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> день <xliff:g id="HOURS">%2$d</xliff:g> ч."</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ч."</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ч. <xliff:g id="MINUTES">%2$d</xliff:g> мин."</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ч. <xliff:g id="MINUTES">%2$d</xliff:g> мин."</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> мин."</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> мин. <xliff:g id="SECONDS">%2$d</xliff:g> с."</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> мин. <xliff:g id="SECONDS">%2$d</xliff:g> с."</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> с."</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> с."</string>
<string name="untitled" msgid="4638956954852782576">"<Без названия>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"..."</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">">999"</string>
<string name="safeMode" msgid="2788228061547930246">"Безопасный режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Личные данные"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Работа"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Платные услуги"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Приложение сможет использовать платные услуги."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Сообщения"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index c96c661..08e4c08 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> d."</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> d. <xliff:g id="HOURS">%2$d</xliff:g> hod."</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> d. <xliff:g id="HOURS">%2$d</xliff:g> hod."</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> hod."</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> hod. <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> hod. <xliff:g id="MINUTES">%2$d</xliff:g> min."</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min."</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min. <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
<string name="untitled" msgid="4638956954852782576">"<Bez mena>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Núdzový režim"</string>
<string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Osobné"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Práca"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Spoplatnené služby"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Vykonávanie činností, ktoré vás môžu stáť peniaze."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Vaše správy"</string>
@@ -409,10 +400,8 @@
<string name="permdesc_bindVpnService" msgid="2067845564581693905">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby VPN. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"väzba na tapetu"</string>
<string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania tapety. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
- <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
- <skip />
- <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
- <skip />
+ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"viazanie na hlasovú interakciu"</string>
+ <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby hlasovej interakcie. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
<string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"viazať na vzdialený displej"</string>
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania vzdialeného displeja. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"viazať sa k službe miniaplikácie"</string>
@@ -725,10 +714,8 @@
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Umožňuje aplikácii načítať, zobrazovať a mazať upozornenia vrátane tých, ktoré boli uverejnené inými aplikáciami."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"naviazanie sa na službu na počúvanie upozornení"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Umožňuje držiteľovi naviazať sa na najvyššiu úroveň služby na počúvanie upozornení. Bežné aplikácie by toto nastavenie nemali nikdy požadovať."</string>
- <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
- <skip />
- <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
- <skip />
+ <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"viazanie na službu poskytovateľa podmienky"</string>
+ <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby poskytovateľa podmienky. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"vyvolanie aplikácie pre konfiguráciu poskytnutú operátorom"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Umožňuje držiteľovi vyvolať aplikáciu pre konfiguráciu poskytnutú operátorom. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"zachytávať informácie o stave siete"</string>
@@ -1399,8 +1386,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Zmeniť tapetu"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"Aplikácia na počúvanie upozornení"</string>
- <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
- <skip />
+ <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Poskytovateľ podmienky"</string>
<string name="vpn_title" msgid="19615213552042827">"Sieť VPN je aktivovaná"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"Aplikáciu <xliff:g id="APP">%s</xliff:g> aktivovala sieť VPN"</string>
<string name="vpn_text" msgid="3011306607126450322">"Dotykom môžete spravovať sieť."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index ef5d872..dfa767b 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"Št. dni: <xliff:g id="DAYS">%1$d</xliff:g>"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dan <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dan <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> h"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> s"</string>
<string name="untitled" msgid="4638956954852782576">"<Brez naslova>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
<string name="safeMode" msgid="2788228061547930246">"Varni način"</string>
<string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Osebno"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Služba"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Plačljive storitve"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Dovolite stvari, za katere bo morda treba plačati."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Vaša sporočila"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index b87bd89..fb65c02 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> дана"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> дан <xliff:g id="HOURS">%2$d</xliff:g> с"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> дан <xliff:g id="HOURS">%2$d</xliff:g> с"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> с"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> с <xliff:g id="MINUTES">%2$d</xliff:g> мин"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> с <xliff:g id="MINUTES">%2$d</xliff:g> мин"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> мин"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> мин <xliff:g id="SECONDS">%2$d</xliff:g> сек"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> мин <xliff:g id="SECONDS">%2$d</xliff:g> сек"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> сек"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> сек"</string>
<string name="untitled" msgid="4638956954852782576">"<Без наслова>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Безбедни режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android систем"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Лично"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Посао"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Услуге које се плаћају"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Покреће радње које могу да се плаћају."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Поруке"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 9b4dae3..ea713a6 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dagar"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> tim"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dag <xliff:g id="HOURS">%2$d</xliff:g> tim"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> timmar"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> tim <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> tim <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> minuter"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sek"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sek"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sekunder"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sekund"</string>
<string name="untitled" msgid="4638956954852782576">"<Okänd>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Säkert läge"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Personligt"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Arbetet"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Tjänster som kostar pengar"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Göra saker som kan kosta pengar."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Dina meddelanden"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 558cae2..8c77050 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"Siku <xliff:g id="DAYS">%1$d</xliff:g>"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"Siku <xliff:g id="DAYS">%1$d</xliff:g> saa <xliff:g id="HOURS">%2$d</xliff:g>"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"Siku <xliff:g id="DAYS">%1$d</xliff:g> saa <xliff:g id="HOURS">%2$d</xliff:g>"</string>
+ <string name="durationHours" msgid="4266858287167358988">"Saa <xliff:g id="HOURS">%1$d</xliff:g>"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"Saa <xliff:g id="HOURS">%1$d</xliff:g> dak <xliff:g id="MINUTES">%2$d</xliff:g>"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"Saa <xliff:g id="HOURS">%1$d</xliff:g> dak <xliff:g id="MINUTES">%2$d</xliff:g>"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"Dakika <xliff:g id="MINUTES">%1$d</xliff:g>"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"Dak <xliff:g id="MINUTES">%1$d</xliff:g> sek <xliff:g id="SECONDS">%2$d</xliff:g>"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"Dak <xliff:g id="MINUTES">%1$d</xliff:g> sek <xliff:g id="SECONDS">%2$d</xliff:g>"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"Sekunde <xliff:g id="SECONDS">%1$d</xliff:g>"</string>
+ <string name="durationSecond" msgid="985669622276420331">"Sekunde <xliff:g id="SECONDS">%1$d</xliff:g>"</string>
<string name="untitled" msgid="4638956954852782576">"<Haina jina>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Mtindo salama"</string>
<string name="android_system_label" msgid="6577375335728551336">"Mfumo wa Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Binafsi"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Kazini"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Huduma ambazo zinakugharimu pesa"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Fanya mambo ambayo yanaweza kukugharimu pesa."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Ujumbe wako"</string>
@@ -409,8 +400,8 @@
<string name="permdesc_bindVpnService" msgid="2067845564581693905">"Inaruhusu kishikiliaji kushurutisha kusano ya kiwango cha juu cha huduma ya Vpn. Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"funga kwa mandhari"</string>
<string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Inaruhusu kishikiliaji kushurutisha kwa kusano ya kiwango cha juu cha mandhari. Haipaswi kamwe kuhitajika kwa programu za kawaida."</string>
- <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"shurutisha kwa muingiliano wa sauti"</string>
- <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Humruhusu mmiliki kushurutisha kwa kiolesura cha hali ya juu cha huduma ya muingiliano wa sauti. Kamwe isihitajike kwa programu za kawaida."</string>
+ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"bandika kwenye mwingiliano wa sauti"</string>
+ <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Humruhusu mmiliki kubandika kwenye kiolesura cha hali ya juu cha huduma ya muingiliano wa sauti. Isihitajike kamwe kwa programu za kawaida."</string>
<string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"fungisha kwenye mwonekano wa mbali"</string>
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Huruhusu mtumiaji kujifungia kiolesura cha kiwango cha juu cha mwonekano wa mbali. Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"funga kwenye huduma ya widget"</string>
@@ -723,8 +714,8 @@
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Huruhusu programu kurejesha, kuchunguza, na kuondoa arifa, ikiwa ni pamoja na zile zilizochapishwa na programu nyingine."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"unganisha kwenye huduma ya kisikilizi cha arifa"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Inaruhusu kishikilizi kuunganishwa kwenye kusano cha kiwango cha juu cha huduma ya kisikilizi cha arifa. Haipaswi kuhitajika tena kwa programu za kawaida."</string>
- <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"shurutisha kwa huduma ya mtoa masharti"</string>
- <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Humruhusu mmiliki kushurutisha kwa kiolesura cha kiwango cha juu cha huduma ya mtoa masharti. Kamwe isihitajike kwa pogramu za kawaida."</string>
+ <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"bandika kwenye huduma ya mtoa masharti"</string>
+ <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Humruhusu mmiliki kubandika kwenye kiolesura cha kiwango cha juu cha huduma ya mtoa masharti. Isihitajike kamwe kwa pogramu za kawaida."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"omba programu ya usakinishaji inayotolewa na mtoa huduma."</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Inaruhusu kishikiliaji kuomba programu ya usakinishaji inayotolewa na mto huduma. Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"sikiliza matukio katika hali za mtandao"</string>
@@ -1395,7 +1386,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"Mandhari"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"Badilisha mandhari"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"Kisikilizi cha arifa"</string>
- <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Mtoa hali"</string>
+ <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Mtoa masharti"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN imewezeshwa"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"VPN imeamilishwa na <xliff:g id="APP">%s</xliff:g>"</string>
<string name="vpn_text" msgid="3011306607126450322">"Gusa ili kudhibiti mtandao."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 826fa64..7f0cf61 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> วัน"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> วัน <xliff:g id="HOURS">%2$d</xliff:g> ชม."</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> วัน <xliff:g id="HOURS">%2$d</xliff:g> ชม."</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> ชม."</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ชม. <xliff:g id="MINUTES">%2$d</xliff:g> นาที"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ชม. <xliff:g id="MINUTES">%2$d</xliff:g> นาที"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> นาที"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> นาที <xliff:g id="SECONDS">%2$d</xliff:g> วิ."</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> นาที <xliff:g id="SECONDS">%2$d</xliff:g> วิ."</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> วินาที"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> วินาที"</string>
<string name="untitled" msgid="4638956954852782576">"<ไม่มีชื่อ>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"โหมดปลอดภัย"</string>
<string name="android_system_label" msgid="6577375335728551336">"ระบบ Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"ส่วนตัว"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"ที่ทำงาน"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"บริการที่ต้องเสียค่าใช้จ่าย"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"ทำสิ่งที่คุณต้องเสียค่าใช้จ่าย"</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"ข้อความของคุณ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 6e50517..969b651 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> (na) araw"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> day <xliff:g id="HOURS">%2$d</xliff:g> hr"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> day <xliff:g id="HOURS">%2$d</xliff:g> hr"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> (na) oras"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> oras <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> oras <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> (na) min"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> seg"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> seg"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> (na) seg"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> (na) seg"</string>
<string name="untitled" msgid="4638956954852782576">"<Walang pamagat>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Personal"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Trabaho"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Mga serbisyong ginagastusan mo"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Gumawa ng mga bagay na magpapagastos sa iyo."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Iyong mga mensahe"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index bd2f926..6e6151f 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> gün"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> gün <xliff:g id="HOURS">%2$d</xliff:g> sa."</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> gün <xliff:g id="HOURS">%2$d</xliff:g> sa."</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> sa."</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> sa. <xliff:g id="MINUTES">%2$d</xliff:g> dk."</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> sa. <xliff:g id="MINUTES">%2$d</xliff:g> dk."</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> dk."</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> dk. <xliff:g id="SECONDS">%2$d</xliff:g> sn."</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> dk. <xliff:g id="SECONDS">%2$d</xliff:g> sn."</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sn."</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sn."</string>
<string name="untitled" msgid="4638956954852782576">"<Adsız>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android Sistemi"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Kişisel"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"İş"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Size maliyet getiren hizmetler"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Size maliyet getirebilecek işlemler yapma."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Mesajlarınız"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index d01c5776..63fdd15 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"Тб"</string>
<string name="petabyteShort" msgid="5637816680144990219">"Пб"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> дн."</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> день <xliff:g id="HOURS">%2$d</xliff:g> год"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> дн. <xliff:g id="HOURS">%2$d</xliff:g> год"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> год"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> год <xliff:g id="MINUTES">%2$d</xliff:g> хв"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> год <xliff:g id="MINUTES">%2$d</xliff:g> хв"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> хв"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> хв <xliff:g id="SECONDS">%2$d</xliff:g> с"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> хв <xliff:g id="SECONDS">%2$d</xliff:g> с"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> с"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> с"</string>
<string name="untitled" msgid="4638956954852782576">"<Без назви>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Безп. режим"</string>
<string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Особистий профіль"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Службовий профіль"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Служби, які потребують оплати"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Виконувати дії, які потребують оплати."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Ваші повідомл."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 24b2db5..545b92e 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> ngày"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> ngày <xliff:g id="HOURS">%2$d</xliff:g> giờ"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> ngày <xliff:g id="HOURS">%2$d</xliff:g> giờ"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> giờ"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> giờ <xliff:g id="MINUTES">%2$d</xliff:g> phút"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> giờ <xliff:g id="MINUTES">%2$d</xliff:g> phút"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> phút"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> phút <xliff:g id="SECONDS">%2$d</xliff:g> giây"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> phút <xliff:g id="SECONDS">%2$d</xliff:g> giây"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> giây"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> giây"</string>
<string name="untitled" msgid="4638956954852782576">"<Không có tiêu đề>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Chế độ an toàn"</string>
<string name="android_system_label" msgid="6577375335728551336">"Hệ thống Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Cá nhân"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Cơ quan"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Dịch vụ tính tiền của bạn"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Thực hiện những tác vụ mà bạn có thể phải trả tiền."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Tin nhắn của bạn"</string>
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
index e71fa4a..44e258d 100644
--- a/core/res/res/values-watch/config.xml
+++ b/core/res/res/values-watch/config.xml
@@ -32,7 +32,7 @@
<dimen name="config_viewConfigurationTouchSlop">4dp</dimen>
<!-- Minimum velocity to initiate a fling, as measured in dips per second. -->
- <dimen name="config_viewMinFlingVelocity">50dp</dimen>
+ <dimen name="config_viewMinFlingVelocity">500dp</dimen>
<!-- Maximum velocity to initiate a fling, as measured in dips per second. -->
<dimen name="config_viewMaxFlingVelocity">8000dp</dimen>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 9297e3a..793e5bf 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g>天"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g>天<xliff:g id="HOURS">%2$d</xliff:g>小时"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g>天<xliff:g id="HOURS">%2$d</xliff:g>小时"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g>小时"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g>小时<xliff:g id="MINUTES">%2$d</xliff:g>分钟"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g>小时<xliff:g id="MINUTES">%2$d</xliff:g>分钟"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g>分钟"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g>分钟<xliff:g id="SECONDS">%2$d</xliff:g>秒"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g>分钟<xliff:g id="SECONDS">%2$d</xliff:g>秒"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g>秒"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g>秒"</string>
<string name="untitled" msgid="4638956954852782576">"<未命名>"</string>
<string name="ellipsis" msgid="7899829516048813237">"..."</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,10 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
+ <!-- no translation found for user_owner_label (2804351898001038951) -->
+ <skip />
+ <!-- no translation found for managed_profile_label (6260850669674791528) -->
+ <skip />
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"需要您付费的服务"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"执行可能需要您付费的操作。"</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"您的信息"</string>
@@ -409,10 +402,8 @@
<string name="permdesc_bindVpnService" msgid="2067845564581693905">"允许用户绑定到 VPN 服务的顶级接口。普通应用绝不需要此权限。"</string>
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"绑定到壁纸"</string>
<string name="permdesc_bindWallpaper" msgid="7108428692595491668">"允许用户绑定到壁纸的顶级接口。普通应用绝不需要此权限。"</string>
- <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
- <skip />
- <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
- <skip />
+ <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"绑定到语音互动器"</string>
+ <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"允许应用绑定到语音互动服务的顶级接口。普通应用绝不需要此权限。"</string>
<string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"绑定至远程显示屏"</string>
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"允许应用绑定至远程显示屏的顶级接口。普通应用绝不需要此权限。"</string>
<string name="permlab_bindRemoteViews" msgid="5697987759897367099">"绑定到小部件服务"</string>
@@ -725,10 +716,8 @@
<string name="permdesc_accessNotifications" msgid="458457742683431387">"允许该应用检索、检查并清除通知,包括其他应用发布的通知。"</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"绑定到通知侦听器服务"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"允许应用绑定到通知侦听器服务的顶级接口(普通应用绝不需要此权限)。"</string>
- <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
- <skip />
- <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
- <skip />
+ <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"绑定到条件提供方服务"</string>
+ <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"允许应用绑定到条件提供方服务的顶级接口。普通应用绝不需要此权限。"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"调用运营商提供的配置应用"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"允许应用调用运营商提供的配置应用。普通应用绝不需要此权限。"</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"监听网络状况的观测信息"</string>
@@ -1399,8 +1388,7 @@
<string name="wallpaper_binding_label" msgid="1240087844304687662">"壁纸"</string>
<string name="chooser_wallpaper" msgid="7873476199295190279">"更改壁纸"</string>
<string name="notification_listener_binding_label" msgid="2014162835481906429">"通知侦听器"</string>
- <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
- <skip />
+ <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"条件提供方"</string>
<string name="vpn_title" msgid="19615213552042827">"VPN 已激活"</string>
<string name="vpn_title_long" msgid="6400714798049252294">"“<xliff:g id="APP">%s</xliff:g>”已激活 VPN"</string>
<string name="vpn_text" msgid="3011306607126450322">"触摸可管理网络。"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 1c8cfe8..fdd02a7 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> 天"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> 天 <xliff:g id="HOURS">%2$d</xliff:g> 小時"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> 天 <xliff:g id="HOURS">%2$d</xliff:g> 小時"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> 小時"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> 小時 <xliff:g id="MINUTES">%2$d</xliff:g> 分鐘"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> 小時 <xliff:g id="MINUTES">%2$d</xliff:g> 分鐘"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> 分鐘"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> 分鐘 <xliff:g id="SECONDS">%2$d</xliff:g> 秒"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> 分鐘 <xliff:g id="SECONDS">%2$d</xliff:g> 秒"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> 秒"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> 秒"</string>
<string name="untitled" msgid="4638956954852782576">"<未命名>"</string>
<string name="ellipsis" msgid="7899829516048813237">"..."</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"個人"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"公司"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"付費服務"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"執行需付費的操作或服務。"</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"您的訊息"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 05e0894..547ca27 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> 天"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> 天 <xliff:g id="HOURS">%2$d</xliff:g> 小時"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> 天 <xliff:g id="HOURS">%2$d</xliff:g> 小時"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> 小時"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> 小時 <xliff:g id="MINUTES">%2$d</xliff:g> 分鐘"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> 小時 <xliff:g id="MINUTES">%2$d</xliff:g> 分鐘"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> 分鐘"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> 分鐘 <xliff:g id="SECONDS">%2$d</xliff:g> 秒"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> 分鐘 <xliff:g id="SECONDS">%2$d</xliff:g> 秒"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> 秒"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> 秒"</string>
<string name="untitled" msgid="4638956954852782576">"<未命名>"</string>
<string name="ellipsis" msgid="7899829516048813237">"…"</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"超過 999"</string>
<string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
<string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"個人"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"公司"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"需要額外費用的服務。"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"執行需付費的作業或服務。"</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"您的簡訊"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 9c8542e..58fdb1c 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -27,28 +27,17 @@
<string name="terabyteShort" msgid="231613018159186962">"TB"</string>
<string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
<string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
- <!-- no translation found for durationDays (6652371460511178259) -->
- <skip />
- <!-- no translation found for durationDayHours (2713107458736744435) -->
- <skip />
- <!-- no translation found for durationDayHour (7293789639090958917) -->
- <skip />
- <!-- no translation found for durationHours (4266858287167358988) -->
- <skip />
- <!-- no translation found for durationHourMinutes (9029176248692041549) -->
- <skip />
- <!-- no translation found for durationHourMinute (2741677355177402539) -->
- <skip />
- <!-- no translation found for durationMinutes (3134226679883579347) -->
- <skip />
- <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
- <skip />
- <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
- <skip />
- <!-- no translation found for durationSeconds (8050088505238241405) -->
- <skip />
- <!-- no translation found for durationSecond (985669622276420331) -->
- <skip />
+ <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> izinsuku"</string>
+ <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> usuku <xliff:g id="HOURS">%2$d</xliff:g> amahora"</string>
+ <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> usuku <xliff:g id="HOURS">%2$d</xliff:g> ihora"</string>
+ <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> amahora"</string>
+ <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> ihora <xliff:g id="MINUTES">%2$d</xliff:g> amaminithi"</string>
+ <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> ihora <xliff:g id="MINUTES">%2$d</xliff:g> iminithi"</string>
+ <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> amaminithi"</string>
+ <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> iminithi <xliff:g id="SECONDS">%2$d</xliff:g> amasekhondi"</string>
+ <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> iminithi <xliff:g id="SECONDS">%2$d</xliff:g> isekhondi"</string>
+ <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> amasekhondi"</string>
+ <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> isekhondi"</string>
<string name="untitled" msgid="4638956954852782576">"<Akunasihloko>"</string>
<string name="ellipsis" msgid="7899829516048813237">"..."</string>
<string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -199,6 +188,8 @@
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"Imodi ephephile"</string>
<string name="android_system_label" msgid="6577375335728551336">"Uhlelo lwe-Android"</string>
+ <string name="user_owner_label" msgid="2804351898001038951">"Okomuntu siqu"</string>
+ <string name="managed_profile_label" msgid="6260850669674791528">"Umsebenzi"</string>
<string name="permgrouplab_costMoney" msgid="5429808217861460401">"Amasevisi abiza imali"</string>
<string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Yenza izinto ezingakudla imali."</string>
<string name="permgrouplab_messages" msgid="7521249148445456662">"Imiyalezo yakho"</string>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 305ba28..f01f10e 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -348,43 +348,4 @@
<item>中文 (繁體)</item>
</string-array>
- <!-- Used by callers to Resources.selectSystemTheme(). Defines the minimum
- targetSdkVersion required for the theme style at a given index.
- NOTE: Must be sorted in ascending order. -->
- <integer-array name="system_theme_sdks">
- <item>0</item>
- <item>11</item>
- <item>14</item>
- <item>21</item>
- </integer-array>
-
- <!-- Used by Resources.selectDefaultTheme(). Defines the default theme style
- for the targetSdkVersion at a given index (see system_theme_sdks).
- NOTE: Must match number of entries in system_theme_sdks. -->
- <array name="system_theme_styles">
- <item>@style/Theme</item>
- <item>@style/Theme.Holo</item>
- <item>@style/Theme.DeviceDefault</item>
- <item>@style/Theme.DeviceDefault.Light.DarkActionBar</item>
- </array>
-
- <!-- Used by ContextImpl for notifications. Defines the default dialog theme
- style for the targetSdkVersion at a given index (see system_theme_sdks).
- NOTE: Must match number of entries in system_theme_sdks. -->
- <array name="system_theme_dialog_styles">
- <item>@style/Theme</item>
- <item>@style/Theme.Holo.Dialog</item>
- <item>@style/Theme.DeviceDefault.Dialog</item>
- <item>@style/Theme.DeviceDefault.Light.Dialog</item>
- </array>
-
- <!-- Used by InputMethodService.onCreate(). Defines the default IME theme
- style for the targetSdkVersion at a given index (see system_theme_sdks).
- NOTE: Must match number of entries in system_theme_sdks. -->
- <array name="system_theme_ime_styles">
- <item>@style/Theme.InputMethod</item>
- <item>@style/Theme.Holo.InputMethod</item>
- <item>@style/Theme.DeviceDefault.InputMethod</item>
- <item>@style/Theme.DeviceDefault.InputMethod</item>
- </array>
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index e07ebd4..0326e18 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -721,6 +721,7 @@
<attr name="actionBarTabBarStyle" format="reference" />
<attr name="actionBarTabTextStyle" format="reference" />
<attr name="actionOverflowButtonStyle" format="reference" />
+ <attr name="actionOverflowMenuStyle" format="reference" />
<!-- Reference to a style for the Action Bar -->
<attr name="actionBarStyle" format="reference" />
<!-- Reference to a style for the split Action Bar. This style
@@ -3803,6 +3804,7 @@
<declare-styleable name="PopupWindow">
<attr name="popupBackground" format="reference|color" />
<attr name="popupAnimationStyle" format="reference" />
+ <attr name="overlapAnchor" format="boolean" />
</declare-styleable>
<declare-styleable name="ViewAnimator">
<!-- Identifier for the animation to use when a view is shown. -->
@@ -5810,6 +5812,9 @@
<attr name="imeExtractExitAnimation" format="reference" />
</declare-styleable>
+ <declare-styleable name="VoiceInteractionSession">
+ </declare-styleable>
+
<declare-styleable name="KeyboardView">
<!-- Default KeyboardView style. -->
<attr name="keyboardViewStyle" format="reference" />
@@ -5951,11 +5956,12 @@
<flag name="vertical" value="0x2" />
</attr>
<!-- Optional parameter which indicates where this widget can be shown,
- ie. home screen, keyguard or both.
- resized. Supports combined values using | operator. -->
+ ie. home screen, keyguard, recents or any combination thereof.
+ Supports combined values using | operator. -->
<attr name="widgetCategory" format="integer">
<flag name="home_screen" value="0x1" />
<flag name="keyguard" value="0x2" />
+ <flag name="recents" value="0x4" />
</attr>
</declare-styleable>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 441fd94..761170d 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -71,11 +71,7 @@
<drawable name="editbox_dropdown_dark_frame">@drawable/editbox_dropdown_background_dark</drawable>
<drawable name="editbox_dropdown_light_frame">@drawable/editbox_dropdown_background</drawable>
- <drawable name="dialog_holo_dark_frame">@drawable/dialog_full_holo_dark</drawable>
- <drawable name="dialog_holo_light_frame">@drawable/dialog_full_holo_light</drawable>
-
<drawable name="input_method_fullscreen_background">#fff9f9f9</drawable>
- <drawable name="input_method_fullscreen_background_holo">@drawable/screen_background_holo_dark</drawable>
<color name="input_method_navigation_guard">#ff000000</color>
<!-- For date picker widget -->
@@ -122,76 +118,8 @@
<!-- FaceLock -->
<color name="facelock_spotlight_mask">#CC000000</color>
- <!-- For holo theme -->
- <drawable name="screen_background_holo_light">#fff3f3f3</drawable>
- <drawable name="screen_background_holo_dark">#ff000000</drawable>
- <color name="background_holo_dark">#ff000000</color>
- <color name="background_holo_light">#fff3f3f3</color>
- <color name="bright_foreground_holo_dark">@android:color/background_holo_light</color>
- <color name="bright_foreground_holo_light">@android:color/background_holo_dark</color>
- <color name="bright_foreground_disabled_holo_dark">#ff4c4c4c</color>
- <color name="bright_foreground_disabled_holo_light">#ffb2b2b2</color>
- <color name="bright_foreground_inverse_holo_dark">@android:color/bright_foreground_holo_light</color>
- <color name="bright_foreground_inverse_holo_light">@android:color/bright_foreground_holo_dark</color>
- <color name="dim_foreground_holo_dark">#bebebe</color>
- <color name="dim_foreground_disabled_holo_dark">#80bebebe</color>
- <color name="dim_foreground_inverse_holo_dark">#323232</color>
- <color name="dim_foreground_inverse_disabled_holo_dark">#80323232</color>
- <color name="hint_foreground_holo_dark">#808080</color>
- <color name="dim_foreground_holo_light">#323232</color>
- <color name="dim_foreground_disabled_holo_light">#80323232</color>
- <color name="dim_foreground_inverse_holo_light">#bebebe</color>
- <color name="dim_foreground_inverse_disabled_holo_light">#80bebebe</color>
- <color name="hint_foreground_holo_light">#808080</color>
- <color name="highlighted_text_holo_dark">#6633b5e5</color>
- <color name="highlighted_text_holo_light">#6633b5e5</color>
- <color name="link_text_holo_dark">#5c5cff</color>
- <color name="link_text_holo_light">#0000ee</color>
-
<color name="micro_text_light">#434343</color>
- <!-- Group buttons -->
- <eat-comment />
- <color name="group_button_dialog_pressed_holo_dark">#46c5c1ff</color>
- <color name="group_button_dialog_focused_holo_dark">#2699cc00</color>
-
- <color name="group_button_dialog_pressed_holo_light">#ffffffff</color>
- <color name="group_button_dialog_focused_holo_light">#4699cc00</color>
-
- <!-- Highlight colors for the legacy themes -->
- <eat-comment />
- <color name="legacy_pressed_highlight">#fffeaa0c</color>
- <color name="legacy_selected_highlight">#fff17a0a</color>
- <color name="legacy_long_pressed_highlight">#ffffffff</color>
-
- <!-- General purpose colors for Holo-themed elements -->
- <eat-comment />
-
- <!-- A light Holo shade of blue -->
- <color name="holo_blue_light">#ff33b5e5</color>
- <!-- A light Holo shade of gray -->
- <color name="holo_gray_light">#33999999</color>
- <!-- A light Holo shade of green -->
- <color name="holo_green_light">#ff99cc00</color>
- <!-- A light Holo shade of red -->
- <color name="holo_red_light">#ffff4444</color>
- <!-- A dark Holo shade of blue -->
- <color name="holo_blue_dark">#ff0099cc</color>
- <!-- A dark Holo shade of green -->
- <color name="holo_green_dark">#ff669900</color>
- <!-- A dark Holo shade of red -->
- <color name="holo_red_dark">#ffcc0000</color>
- <!-- A Holo shade of purple -->
- <color name="holo_purple">#ffaa66cc</color>
- <!-- A light Holo shade of orange -->
- <color name="holo_orange_light">#ffffbb33</color>
- <!-- A dark Holo shade of orange -->
- <color name="holo_orange_dark">#ffff8800</color>
- <!-- A really bright Holo shade of blue -->
- <color name="holo_blue_bright">#ff00ddff</color>
- <!-- A really bright Holo shade of gray -->
- <color name="holo_gray_bright">#33CCCCCC</color>
-
<drawable name="notification_template_icon_bg">#3333B5E5</drawable>
<drawable name="notification_template_icon_low_bg">#0cffffff</drawable>
@@ -206,21 +134,5 @@
<color name="accessibility_focus_highlight">#80ffff00</color>
- <!-- New TimePicker colors -->
- <color name="timepicker_default_background_holo_light">@android:color/white</color>
- <color name="timepicker_default_background_holo_dark">#ff303030</color>
-
- <color name="timepicker_default_text_color_holo_light">#8c8c8c</color>
- <color name="timepicker_default_text_color_holo_dark">@android:color/white</color>
-
- <color name="timepicker_default_disabled_color_holo_light">#7f000000</color>
- <color name="timepicker_default_disabled_color_holo_dark">#7f08c8c8</color>
-
- <color name="timepicker_default_ampm_selected_background_color_holo_light">@android:color/holo_blue_light</color>
- <color name="timepicker_default_ampm_selected_background_color_holo_dark">@android:color/holo_blue_light</color>
-
- <color name="timepicker_default_ampm_unselected_background_color_holo_light">@android:color/white</color>
- <color name="timepicker_default_ampm_unselected_background_color_holo_dark">@android:color/transparent</color>
-
</resources>
diff --git a/core/res/res/values/colors_holo.xml b/core/res/res/values/colors_holo.xml
new file mode 100644
index 0000000..d1f4e38
--- /dev/null
+++ b/core/res/res/values/colors_holo.xml
@@ -0,0 +1,123 @@
+<?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.
+-->
+
+<!-- Colors specific to Holo themes. -->
+<resources>
+
+ <drawable name="dialog_holo_dark_frame">@drawable/dialog_full_holo_dark</drawable>
+ <drawable name="dialog_holo_light_frame">@drawable/dialog_full_holo_light</drawable>
+ <drawable name="input_method_fullscreen_background_holo">@drawable/screen_background_holo_dark</drawable>
+
+ <drawable name="screen_background_holo_light">#fff3f3f3</drawable>
+ <drawable name="screen_background_holo_dark">#ff000000</drawable>
+
+ <color name="background_holo_dark">#ff000000</color>
+ <color name="background_holo_light">#fff3f3f3</color>
+ <color name="bright_foreground_holo_dark">@color/background_holo_light</color>
+ <color name="bright_foreground_holo_light">@color/background_holo_dark</color>
+ <color name="bright_foreground_disabled_holo_dark">#ff4c4c4c</color>
+ <color name="bright_foreground_disabled_holo_light">#ffb2b2b2</color>
+ <color name="bright_foreground_inverse_holo_dark">@color/bright_foreground_holo_light</color>
+ <color name="bright_foreground_inverse_holo_light">@color/bright_foreground_holo_dark</color>
+ <color name="dim_foreground_holo_dark">#bebebe</color>
+ <color name="dim_foreground_disabled_holo_dark">#80bebebe</color>
+ <color name="dim_foreground_inverse_holo_dark">#323232</color>
+ <color name="dim_foreground_inverse_disabled_holo_dark">#80323232</color>
+ <color name="hint_foreground_holo_dark">#808080</color>
+ <color name="dim_foreground_holo_light">#323232</color>
+ <color name="dim_foreground_disabled_holo_light">#80323232</color>
+ <color name="dim_foreground_inverse_holo_light">#bebebe</color>
+ <color name="dim_foreground_inverse_disabled_holo_light">#80bebebe</color>
+ <color name="hint_foreground_holo_light">#808080</color>
+ <color name="highlighted_text_holo_dark">#6633b5e5</color>
+ <color name="highlighted_text_holo_light">#6633b5e5</color>
+ <color name="link_text_holo_dark">#5c5cff</color>
+ <color name="link_text_holo_light">#0000ee</color>
+
+ <!-- General purpose colors for Holo-themed elements -->
+ <eat-comment />
+
+ <!-- A light Holo shade of blue -->
+ <color name="holo_blue_light">#ff33b5e5</color>
+ <!-- A light Holo shade of gray -->
+ <color name="holo_gray_light">#33999999</color>
+ <!-- A light Holo shade of green -->
+ <color name="holo_green_light">#ff99cc00</color>
+ <!-- A light Holo shade of red -->
+ <color name="holo_red_light">#ffff4444</color>
+ <!-- A dark Holo shade of blue -->
+ <color name="holo_blue_dark">#ff0099cc</color>
+ <!-- A dark Holo shade of green -->
+ <color name="holo_green_dark">#ff669900</color>
+ <!-- A dark Holo shade of red -->
+ <color name="holo_red_dark">#ffcc0000</color>
+ <!-- A Holo shade of purple -->
+ <color name="holo_purple">#ffaa66cc</color>
+ <!-- A light Holo shade of orange -->
+ <color name="holo_orange_light">#ffffbb33</color>
+ <!-- A dark Holo shade of orange -->
+ <color name="holo_orange_dark">#ffff8800</color>
+ <!-- A really bright Holo shade of blue -->
+ <color name="holo_blue_bright">#ff00ddff</color>
+ <!-- A really bright Holo shade of gray -->
+ <color name="holo_gray_bright">#33CCCCCC</color>
+
+ <!-- Forward compatibility for Quantum-style theme colors -->
+ <eat-comment />
+
+ <color name="holo_primary_dark">#ff000000</color>
+ <color name="holo_primary">#ffe6e6e6</color>
+ <color name="holo_primary_light">#ffffffff</color>
+ <color name="holo_control_activated">@color/holo_blue_light</color>
+ <color name="holo_control_normal">#39cccccc</color>
+ <color name="holo_button_pressed">#59f0f0f0</color>
+ <color name="holo_button_normal">#bd292f34</color>
+
+ <color name="holo_light_primary_dark">#ff000000</color>
+ <color name="holo_light_primary">#ffe6e6e6</color>
+ <color name="holo_light_primary_light">#ffffffff</color>
+ <color name="holo_light_control_activated">@color/holo_control_activated</color>
+ <color name="holo_light_control_normal">#dacccccc</color>
+ <color name="holo_light_button_pressed">#66666666</color>
+ <color name="holo_light_button_normal">#b3cccccc</color>
+
+ <!-- Group buttons -->
+ <eat-comment />
+
+ <color name="group_button_dialog_pressed_holo_dark">#46c5c1ff</color>
+ <color name="group_button_dialog_focused_holo_dark">#2699cc00</color>
+
+ <color name="group_button_dialog_pressed_holo_light">#ffffffff</color>
+ <color name="group_button_dialog_focused_holo_light">#4699cc00</color>
+
+ <!-- Time picker -->
+ <eat-comment />
+
+ <color name="timepicker_default_background_holo_light">@color/white</color>
+ <color name="timepicker_default_background_holo_dark">#ff303030</color>
+
+ <color name="timepicker_default_text_color_holo_light">#8c8c8c</color>
+ <color name="timepicker_default_text_color_holo_dark">@color/white</color>
+
+ <color name="timepicker_default_disabled_color_holo_light">#7f000000</color>
+ <color name="timepicker_default_disabled_color_holo_dark">#7f08c8c8</color>
+
+ <color name="timepicker_default_ampm_selected_background_color_holo_light">@color/holo_blue_light</color>
+ <color name="timepicker_default_ampm_selected_background_color_holo_dark">@color/holo_blue_light</color>
+
+ <color name="timepicker_default_ampm_unselected_background_color_holo_light">@color/white</color>
+ <color name="timepicker_default_ampm_unselected_background_color_holo_dark">@color/transparent</color>
+</resources>
diff --git a/core/res/res/values/colors_legacy.xml b/core/res/res/values/colors_legacy.xml
new file mode 100644
index 0000000..48d4b42
--- /dev/null
+++ b/core/res/res/values/colors_legacy.xml
@@ -0,0 +1,45 @@
+<?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.
+-->
+
+<!-- Colors specific to pre-Holo themes. -->
+<resources>
+
+ <!-- Highlight colors for the legacy themes -->
+ <eat-comment />
+
+ <color name="legacy_pressed_highlight">#fffeaa0c</color>
+ <color name="legacy_selected_highlight">#fff17a0a</color>
+ <color name="legacy_long_pressed_highlight">#ffffffff</color>
+
+ <!-- Forward compatibility for Quantum-style theme colors -->
+ <eat-comment />
+
+ <color name="legacy_primary_dark">#ff000000</color>
+ <color name="legacy_primary">#ffe6e6e6</color>
+ <color name="legacy_primary_light">#ffffffff</color>
+ <color name="legacy_control_activated">#ff90df25</color>
+ <color name="legacy_control_normal">#99ffffff</color>
+ <color name="legacy_button_pressed">#fffea50b</color>
+ <color name="legacy_button_normal">#f3dbdbdb</color>
+
+ <color name="legacy_light_primary_dark">@color/legacy_primary_dark</color>
+ <color name="legacy_light_primary">@color/legacy_primary</color>
+ <color name="legacy_light_primary_light">@color/legacy_primary_light</color>
+ <color name="legacy_light_control_activated">@color/legacy_control_activated</color>
+ <color name="legacy_light_control_normal">#99000000</color>
+ <color name="legacy_light_button_pressed">@color/legacy_button_pressed</color>
+ <color name="legacy_light_button_normal">@color/legacy_button_normal</color>
+</resources>
diff --git a/core/res/res/values/colors_quantum.xml b/core/res/res/values/colors_quantum.xml
index f8f192f..7171450 100644
--- a/core/res/res/values/colors_quantum.xml
+++ b/core/res/res/values/colors_quantum.xml
@@ -14,6 +14,7 @@
limitations under the License.
-->
+<!-- Colors specific to Quantum themes. -->
<resources>
<color name="background_quantum_dark">@color/black</color>
<color name="background_quantum_light">@color/white</color>
@@ -40,6 +41,7 @@
<color name="highlighted_text_quantum_light">#660097a7</color>
<!-- Primary & accent colors -->
+ <eat-comment />
<color name="quantum_red_100">#fff4c7c3</color>
<color name="quantum_red_300">#ffe67c73</color>
@@ -98,6 +100,7 @@
<color name="quantum_deep_orange_A400">#ffff1744</color>
<!-- Neutral colors -->
+ <eat-comment />
<color name="quantum_grey_50">#fffafafa</color>
<color name="quantum_grey_100">#fff5f5f5</color>
@@ -117,6 +120,7 @@
<color name="quantum_brown_700">#ff5d4037</color>
<!-- Text & foreground colors -->
+ <eat-comment />
<color name="primary_text_default_quantum_light">#de000000</color>
<color name="secondary_text_quantum_light">#8a000000</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 624ed73..f39155b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1212,6 +1212,9 @@
<!-- Maximum velocity to initiate a fling, as measured in dips per second. -->
<dimen name="config_viewMaxFlingVelocity">8000dp</dimen>
+ <!-- Amount of time in ms the user needs to press the relevant key to bring up the global actions dialog -->
+ <integer name="config_globalActionsKeyTimeout">500</integer>
+
<!-- Maximum number of grid columns permitted in the ResolverActivity
used for picking activities to handle an intent. -->
<integer name="config_maxResolverActivityColumns">2</integer>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 22c2b050..e88a6ee 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2168,6 +2168,7 @@
<public type="attr" name="excludeId" />
<public type="attr" name="excludeClass" />
<public type="attr" name="hideOnContentScroll" />
+ <public type="attr" name="actionOverflowMenuStyle" />
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
@@ -2285,8 +2286,6 @@
<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.Button.Paper" />
- <public type="style" name="Widget.Quantum.Button.Paper.Color" />
<public type="style" name="Widget.Quantum.ButtonBar" />
<public type="style" name="Widget.Quantum.ButtonBar.AlertDialog" />
<public type="style" name="Widget.Quantum.CalendarView" />
@@ -2309,6 +2308,7 @@
<public type="style" name="Widget.Quantum.ListView.DropDown" />
<public type="style" name="Widget.Quantum.MediaRouteButton" />
<public type="style" name="Widget.Quantum.PopupMenu" />
+ <public type="style" name="Widget.Quantum.PopupMenu.Overflow" />
<public type="style" name="Widget.Quantum.PopupWindow" />
<public type="style" name="Widget.Quantum.ProgressBar" />
<public type="style" name="Widget.Quantum.ProgressBar.Horizontal" />
@@ -2347,8 +2347,6 @@
<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.Button.Paper" />
- <public type="style" name="Widget.Quantum.Light.Button.Paper.Color" />
<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" />
@@ -2370,6 +2368,7 @@
<public type="style" name="Widget.Quantum.Light.ListView.DropDown" />
<public type="style" name="Widget.Quantum.Light.MediaRouteButton" />
<public type="style" name="Widget.Quantum.Light.PopupMenu" />
+ <public type="style" name="Widget.Quantum.Light.PopupMenu.Overflow" />
<public type="style" name="Widget.Quantum.Light.PopupWindow" />
<public type="style" name="Widget.Quantum.Light.ProgressBar" />
<public type="style" name="Widget.Quantum.Light.ProgressBar.Horizontal" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 37716f7..891265f 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -169,6 +169,12 @@
<item name="windowExitAnimation">@anim/input_method_exit</item>
</style>
+ <!-- Window animations that are applied to voice interaction overlay windows. -->
+ <style name="Animation.VoiceInteractionSession">
+ <item name="windowEnterAnimation">@anim/input_method_enter</item>
+ <item name="windowExitAnimation">@anim/input_method_exit</item>
+ </style>
+
<!-- Special optional fancy IM animations. @hide -->
<style name="Animation.InputMethodFancy">
<item name="windowEnterAnimation">@anim/input_method_fancy_enter</item>
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index 23172c1..01c3017 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -372,16 +372,6 @@
<item name="minWidth">48dip</item>
</style>
- <!-- Bordered paper button -->
- <style name="Widget.Quantum.Button.Paper">
- <!-- TODO: Specify pressed state animation. -->
- </style>
-
- <!-- Bordered paper button with color -->
- <style name="Widget.Quantum.Button.Paper.Color">
- <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</item>
@@ -393,11 +383,6 @@
<item name="minWidth">48dip</item>
</style>
- <!-- Borderless paper button -->
- <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>
@@ -680,7 +665,8 @@
<style name="Widget.Quantum.ListPopupWindow" parent="Widget.ListPopupWindow">
<item name="dropDownSelector">@drawable/list_selector_quantum</item>
- <item name="popupBackground">?attr/colorBackground</item>
+ <item name="popupBackground">@drawable/popup_background_quantum</item>
+ <item name="popupAnimationStyle">@style/Animation.Quantum.Popup</item>
<item name="dropDownVerticalOffset">0dip</item>
<item name="dropDownHorizontalOffset">0dip</item>
<item name="dropDownWidth">wrap_content</item>
@@ -688,6 +674,10 @@
<style name="Widget.Quantum.PopupMenu" parent="Widget.Quantum.ListPopupWindow"/>
+ <style name="Widget.Quantum.PopupMenu.Overflow">
+ <item name="overlapAnchor">true</item>
+ </style>
+
<style name="Widget.Quantum.ActionButton" parent="Widget.ActionButton">
<item name="minWidth">@dimen/action_button_min_width_quantum</item>
<item name="minHeight">@dimen/action_button_min_height_quantum</item>
@@ -784,11 +774,8 @@
<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">
@@ -925,17 +912,9 @@
<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_quantum</item>
- <item name="popupBackground">?attr/colorBackground</item>
- <item name="dropDownVerticalOffset">0dip</item>
- <item name="dropDownHorizontalOffset">0dip</item>
- <item name="dropDownWidth">wrap_content</item>
- </style>
-
- <style name="Widget.Quantum.Light.PopupMenu" parent="Widget.Quantum.Light.ListPopupWindow"/>
-
+ <style name="Widget.Quantum.Light.ListPopupWindow" parent="Widget.Quantum.ListPopupWindow"/>
+ <style name="Widget.Quantum.Light.PopupMenu" parent="Widget.Quantum.ListPopupWindow"/>
+ <style name="Widget.Quantum.Light.PopupMenu.Overflow" parent="Widget.Quantum.PopupMenu.Overflow"/>
<style name="Widget.Quantum.Light.ActionButton" parent="Widget.Quantum.ActionButton"/>
<style name="Widget.Quantum.Light.ActionButton.Overflow" parent="Widget.Quantum.ActionButton.Overflow"/>
<style name="Widget.Quantum.Light.Tab" parent="Widget.Quantum.Tab"/>
@@ -979,7 +958,16 @@
<style name="Animation.Quantum" parent="Animation"/>
<style name="Animation.Quantum.Activity" parent="Animation.Activity"/>
- <style name="Animation.Quantum.Dialog" parent="Animation.Dialog"/>
+
+ <style name="Animation.Quantum.Dialog">
+ <item name="windowEnterAnimation">@anim/popup_enter_quantum</item>
+ <item name="windowExitAnimation">@anim/popup_exit_quantum</item>
+ </style>
+
+ <style name="Animation.Quantum.Popup">
+ <item name="windowEnterAnimation">@anim/popup_enter_quantum</item>
+ <item name="windowExitAnimation">@anim/popup_exit_quantum</item>
+ </style>
<!-- Dialog styles -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 516a13b..a8a4b51 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1198,6 +1198,7 @@
<java-symbol type="layout" name="transient_notification" />
<java-symbol type="layout" name="volume_adjust" />
<java-symbol type="layout" name="volume_adjust_item" />
+ <java-symbol type="layout" name="voice_interaction_session" />
<java-symbol type="layout" name="web_text_view_dropdown" />
<java-symbol type="layout" name="webview_find" />
<java-symbol type="layout" name="webview_select_singlechoice" />
@@ -1269,6 +1270,7 @@
<java-symbol type="style" name="TextAppearance.SlidingTabNormal" />
<java-symbol type="style" name="Theme.DeviceDefault.Dialog.NoFrame" />
<java-symbol type="style" name="Theme.IconMenu" />
+ <java-symbol type="style" name="Theme.DeviceDefault.VoiceInteractionSession" />
<java-symbol type="attr" name="mediaRouteButtonStyle" />
<java-symbol type="attr" name="externalRouteEnabledDrawable" />
@@ -1649,6 +1651,7 @@
<java-symbol type="id" name="resolver_list" />
<java-symbol type="id" name="button_once" />
<java-symbol type="id" name="button_always" />
+ <java-symbol type="integer" name="config_globalActionsKeyTimeout" />
<java-symbol type="integer" name="config_maxResolverActivityColumns" />
<java-symbol type="array" name="config_notificationScorers" />
@@ -1861,9 +1864,5 @@
<java-symbol type="id" name="icon_frame" />
<java-symbol type="style" name="Animation.VolumePanel" />
<java-symbol type="transition" name="no_transition" />
- <java-symbol type="array" name="system_theme_sdks" />
- <java-symbol type="array" name="system_theme_styles" />
- <java-symbol type="array" name="system_theme_dialog_styles" />
- <java-symbol type="array" name="system_theme_ime_styles" />
</resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 7b3d5e3..34ef508 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -53,6 +53,14 @@
<item name="colorMultiSelectHighlight">@color/legacy_selected_highlight</item>
<item name="colorActivatedHighlight">@color/legacy_selected_highlight</item>
+ <item name="colorPrimaryDark">@color/legacy_primary_dark</item>
+ <item name="colorPrimary">@color/legacy_primary</item>
+ <item name="colorPrimaryLight">@color/legacy_primary_light</item>
+ <item name="colorControlActivated">@color/legacy_control_activated</item>
+ <item name="colorControlNormal">@color/legacy_control_normal</item>
+ <item name="colorButtonPressed">@color/legacy_button_pressed</item>
+ <item name="colorButtonNormal">@color/legacy_button_normal</item>
+
<item name="disabledAlpha">0.5</item>
<item name="backgroundDimAmount">0.6</item>
@@ -328,6 +336,7 @@
<item name="actionDropDownStyle">@android:style/Widget.Spinner.DropDown</item>
<item name="actionButtonStyle">@android:style/Widget.ActionButton</item>
<item name="actionOverflowButtonStyle">@android:style/Widget.ActionButton.Overflow</item>
+ <item name="actionOverflowMenuStyle">?android:attr/popupMenuStyle</item>
<item name="actionModeBackground">@android:drawable/cab_background_top_holo_dark</item>
<item name="actionModeSplitBackground">@null</item>
<item name="actionModeCloseDrawable">@android:drawable/ic_menu_close_clear_cancel</item>
@@ -437,6 +446,14 @@
<item name="colorBackground">@android:color/background_light</item>
<item name="colorForeground">@color/bright_foreground_light</item>
<item name="colorForegroundInverse">@android:color/bright_foreground_light_inverse</item>
+
+ <item name="colorPrimaryDark">@color/legacy_light_primary_dark</item>
+ <item name="colorPrimary">@color/legacy_light_primary</item>
+ <item name="colorPrimaryLight">@color/legacy_light_primary_light</item>
+ <item name="colorControlActivated">@color/legacy_light_control_activated</item>
+ <item name="colorControlNormal">@color/legacy_light_control_normal</item>
+ <item name="colorButtonPressed">@color/legacy_light_button_pressed</item>
+ <item name="colorButtonNormal">@color/legacy_light_button_normal</item>
<item name="textColorPrimary">@android:color/primary_text_light</item>
<item name="textColorSecondary">@android:color/secondary_text_light</item>
@@ -789,6 +806,14 @@
<item name="android:imeExtractExitAnimation">@android:anim/input_method_extract_exit</item>
</style>
+ <!-- Default theme for voice interaction, which is used by the
+ {@link android.service.voice.VoiceInteractionSession} class.
+ this inherits from Theme.Panel, but sets up appropriate animations
+ and a few custom attributes. -->
+ <style name="Theme.VoiceInteractionSession" parent="Theme.Panel">
+ <item name="android:windowAnimationStyle">@android:style/Animation.VoiceInteractionSession</item>
+ </style>
+
<!-- Default theme for holo style input methods, which is used by the
{@link android.inputmethodservice.InputMethodService} class.
this inherits from Theme.Panel, but sets up IME appropriate animations
@@ -937,6 +962,14 @@
<item name="colorMultiSelectHighlight">@color/holo_green_light</item>
<item name="colorActivatedHighlight">@color/holo_blue_dark</item>
+ <item name="colorPrimaryDark">@color/holo_primary_dark</item>
+ <item name="colorPrimary">@color/holo_primary</item>
+ <item name="colorPrimaryLight">@color/holo_primary_light</item>
+ <item name="colorControlActivated">@color/holo_control_activated</item>
+ <item name="colorControlNormal">@color/holo_control_normal</item>
+ <item name="colorButtonPressed">@color/holo_button_pressed</item>
+ <item name="colorButtonNormal">@color/holo_button_normal</item>
+
<!-- Text styles -->
<item name="textAppearance">@android:style/TextAppearance.Holo</item>
<item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Inverse</item>
@@ -1181,6 +1214,7 @@
<item name="actionDropDownStyle">@android:style/Widget.Holo.Spinner.DropDown.ActionBar</item>
<item name="actionButtonStyle">@android:style/Widget.Holo.ActionButton</item>
<item name="actionOverflowButtonStyle">@android:style/Widget.Holo.ActionButton.Overflow</item>
+ <item name="actionOverflowMenuStyle">?android:attr/popupMenuStyle</item>
<item name="actionModeBackground">@android:drawable/cab_background_top_holo_dark</item>
<item name="actionModeSplitBackground">@android:drawable/cab_background_bottom_holo_dark</item>
<item name="actionModeCloseDrawable">@android:drawable/ic_cab_done_holo_dark</item>
@@ -1268,6 +1302,14 @@
<item name="colorMultiSelectHighlight">@color/holo_green_light</item>
<item name="colorActivatedHighlight">@color/holo_blue_dark</item>
+ <item name="colorPrimaryDark">@color/holo_light_primary_dark</item>
+ <item name="colorPrimary">@color/holo_light_primary</item>
+ <item name="colorPrimaryLight">@color/holo_light_primary_light</item>
+ <item name="colorControlActivated">@color/holo_light_control_activated</item>
+ <item name="colorControlNormal">@color/holo_light_control_normal</item>
+ <item name="colorButtonPressed">@color/holo_light_button_pressed</item>
+ <item name="colorButtonNormal">@color/holo_light_button_normal</item>
+
<!-- Text styles -->
<item name="textAppearance">@android:style/TextAppearance.Holo.Light</item>
<item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Light.Inverse</item>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 80c10dd..dbc3d9e 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -299,6 +299,11 @@
{@link android.inputmethodservice.InputMethodService} class.-->
<style name="Theme.DeviceDefault.InputMethod" parent="Theme.Quantum.InputMethod" />
+ <!-- DeviceDefault style for input methods, which is used by the
+ {@link android.service.voice.VoiceInteractionSession} class.-->
+ <style name="Theme.DeviceDefault.VoiceInteractionSession" parent="Theme.Quantum.VoiceInteractionSession" >
+
+ </style>
<style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Quantum.Dialog.Alert">
<item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault</item>
</style>
diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml
index e3ac1ad..39c8beb 100644
--- a/core/res/res/values/themes_quantum.xml
+++ b/core/res/res/values/themes_quantum.xml
@@ -291,6 +291,7 @@
<item name="actionDropDownStyle">@style/Widget.Quantum.Spinner.DropDown.ActionBar</item>
<item name="actionButtonStyle">@style/Widget.Quantum.ActionButton</item>
<item name="actionOverflowButtonStyle">@style/Widget.Quantum.ActionButton.Overflow</item>
+ <item name="actionOverflowMenuStyle">@android:style/Widget.Quantum.PopupMenu.Overflow</item>
<item name="actionModeBackground">?attr/colorPrimaryDark</item>
<item name="actionModeSplitBackground">?attr/colorPrimaryDark</item>
<item name="actionModeCloseDrawable">@drawable/ic_cab_done_quantum</item>
@@ -636,6 +637,7 @@
<item name="actionDropDownStyle">@style/Widget.Quantum.Light.Spinner.DropDown.ActionBar</item>
<item name="actionButtonStyle">@style/Widget.Quantum.Light.ActionButton</item>
<item name="actionOverflowButtonStyle">@style/Widget.Quantum.Light.ActionButton.Overflow</item>
+ <item name="actionOverflowMenuStyle">@android:style/Widget.Quantum.Light.PopupMenu.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</item>
@@ -717,9 +719,6 @@
<item name="colorControlActivated">?attr/colorPrimary</item>
<item name="colorButtonNormal">@color/quantum_grey_100</item>
<item name="colorButtonPressed">@color/quantum_grey_500</item>
- <!-- TODO: Remove these attrs and move into button style. -->
- <item name="colorButtonNormalColored">?attr/colorPrimary</item>
- <item name="colorButtonPressedColored">?attr/colorPrimaryDark</item>
</style>
<style name="ThemeOverlay" />
@@ -856,6 +855,14 @@
<item name="imeExtractExitAnimation">@anim/input_method_extract_exit</item>
</style>
+ <!-- Default theme for quantum style voice interaction, which is used by the
+ {@link android.service.voice.VoiceInteractionSession} class.
+ this inherits from Theme.Panel, but sets up appropriate animations
+ and a few custom attributes. -->
+ <style name="Theme.Quantum.VoiceInteractionSession" parent="Theme.Quantum.Light.Panel">
+ <item name="android:windowAnimationStyle">@android:style/Animation.VoiceInteractionSession</item>
+ </style>
+
<!-- Theme for the search input bar. -->
<style name="Theme.Quantum.SearchBar" parent="Theme.Quantum.Panel">
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
index 0cd19f2..67203b2 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
@@ -64,6 +64,8 @@
unpairAll();
} else if ("getName".equals(command)) {
getName();
+ } else if ("getAddress".equals(command)) {
+ getAddress();
} else {
finish(null);
}
@@ -90,6 +92,12 @@
finish(mSuccessResult);
}
+ public void getAddress() {
+ String name = getBluetoothAdapter().getAddress();
+ mSuccessResult.putString("address", name);
+ finish(mSuccessResult);
+ }
+
public void finish(Bundle result) {
if (result == null) {
result = new Bundle();
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java
new file mode 100644
index 0000000..0f3ea0e
--- /dev/null
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothUuidTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.bluetooth;
+
+import android.os.ParcelUuid;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit test cases for {@link BluetoothUuid}.
+ * <p>
+ * To run this test, use adb shell am instrument -e class 'android.bluetooth.BluetoothUuidTest' -w
+ * 'com.android.bluetooth.tests/android.bluetooth.BluetoothTestRunner'
+ */
+public class BluetoothUuidTest extends TestCase {
+
+ @SmallTest
+ public void testUuidParser() {
+ byte[] uuid16 = new byte[] {
+ 0x0B, 0x11 };
+ assertEquals(ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB"),
+ BluetoothUuid.parseUuidFrom(uuid16));
+
+ byte[] uuid32 = new byte[] {
+ 0x0B, 0x11, 0x33, (byte) 0xFE };
+ assertEquals(ParcelUuid.fromString("FE33110B-0000-1000-8000-00805F9B34FB"),
+ BluetoothUuid.parseUuidFrom(uuid32));
+
+ byte[] uuid128 = new byte[] {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, (byte) 0xFF };
+ assertEquals(ParcelUuid.fromString("FF0F0E0D-0C0B-0A09-0807-0060504030201"),
+ BluetoothUuid.parseUuidFrom(uuid128));
+ }
+}
diff --git a/core/tests/coretests/src/android/net/RssiCurveTest.java b/core/tests/coretests/src/android/net/RssiCurveTest.java
new file mode 100644
index 0000000..d4438df
--- /dev/null
+++ b/core/tests/coretests/src/android/net/RssiCurveTest.java
@@ -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
+ */
+
+package android.net;
+
+import junit.framework.TestCase;
+
+public class RssiCurveTest extends TestCase {
+ public void testLookupScore_constantCurve() {
+ RssiCurve curve = new RssiCurve(-100, 200, new byte[] { 10 });
+ assertEquals(10, curve.lookupScore(-200));
+ assertEquals(10, curve.lookupScore(-100));
+ assertEquals(10, curve.lookupScore(0));
+ assertEquals(10, curve.lookupScore(100));
+ assertEquals(10, curve.lookupScore(200));
+ }
+
+ public void testLookupScore_changingCurve() {
+ RssiCurve curve = new RssiCurve(-100, 100, new byte[] { -10, 10 });
+ assertEquals(-10, curve.lookupScore(-200));
+ assertEquals(-10, curve.lookupScore(-100));
+ assertEquals(-10, curve.lookupScore(-50));
+ assertEquals(10, curve.lookupScore(0));
+ assertEquals(10, curve.lookupScore(50));
+ assertEquals(10, curve.lookupScore(100));
+ assertEquals(10, curve.lookupScore(200));
+ }
+}
diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
index 6d33529..23b6780 100644
--- a/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
@@ -73,7 +73,6 @@
DUMMY_FORCE_DEFAULT, supportsSwitchingToNextInputMethod);
for (int i = 0; i < subtypes.size(); ++i) {
final String subtypeLocale = subtypeLocales.get(i);
- final InputMethodSubtype subtype = subtypes.get(i);
items.add(new ImeSubtypeListItem(imeName, subtypeLocale, imi, i, subtypeLocale,
SYSTEM_LOCALE));
}
@@ -116,36 +115,37 @@
imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
currentIme.mSubtypeName.toString()));
assertEquals(imList.get(2), nextIme);
- // "switchAwareLatinIme/fr" -> "nonSwitchAwareLatinIme/en_UK
+ // "switchAwareLatinIme/fr" -> "switchAwareJapaneseIme/ja_JP"
currentIme = imList.get(2);
nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
currentIme.mSubtypeName.toString()));
- assertEquals(imList.get(3), nextIme);
+ assertEquals(imList.get(5), nextIme);
+ // "switchAwareJapaneseIme/ja_JP" -> "switchAwareLatinIme/en_US"
+ currentIme = imList.get(5);
+ nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+ imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+ currentIme.mSubtypeName.toString()));
+ assertEquals(imList.get(0), nextIme);
+
// "nonSwitchAwareLatinIme/en_UK" -> "nonSwitchAwareLatinIme/hi"
currentIme = imList.get(3);
nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
currentIme.mSubtypeName.toString()));
assertEquals(imList.get(4), nextIme);
- // "nonSwitchAwareLatinIme/hi" -> "switchAwareJapaneseIme/ja_JP"
+ // "nonSwitchAwareLatinIme/hi" -> "nonSwitchAwareJapaneseIme/ja_JP"
currentIme = imList.get(4);
nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
currentIme.mSubtypeName.toString()));
- assertEquals(imList.get(5), nextIme);
- // "switchAwareJapaneseIme/ja_JP" -> "nonSwitchAwareJapaneseIme/ja_JP"
- currentIme = imList.get(5);
- nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
- imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
- currentIme.mSubtypeName.toString()));
assertEquals(imList.get(6), nextIme);
- // "nonSwitchAwareJapaneseIme/ja_JP" -> "switchAwareLatinIme/en_US"
+ // "nonSwitchAwareJapaneseIme/ja_JP" -> "nonSwitchAwareLatinIme/en_UK"
currentIme = imList.get(6);
nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
currentIme.mSubtypeName.toString()));
- assertEquals(imList.get(0), nextIme);
+ assertEquals(imList.get(3), nextIme);
}
@SmallTest
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 56423c9..cfc1484 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -404,6 +404,8 @@
# key 503 KEY_BRL_DOT7
# key 504 KEY_BRL_DOT8
+key 580 APP_SWITCH
+
# Keys defined by HID usages
key usage 0x0c006F BRIGHTNESS_UP
key usage 0x0c0070 BRIGHTNESS_DOWN
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index 92ecd24..bddb8ec 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 April 1, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on May 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 April 1, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on May 1, 2014.
<br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
@@ -111,7 +111,7 @@
<img alt="" style="float:right"
-src="//chart.googleapis.com/chart?chl=GL%201.1%20only%7CGL%202.0%7CGL%203.0&chf=bg%2Cs%2C00000000&chd=t%3A0.1%2C93.5%2C6.4&chco=c4df9b%2C6fad0c&chs=400x250&cht=p" />
+src="//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A0.1%2C87.0%2C12.9&chf=bg%2Cs%2C00000000&chl=GL%201.1%20only%7CGL%202.0%7CGL%203.0&chco=c4df9b%2C6fad0c" />
<p>To declare which version of OpenGL ES your application requires, you should use the {@code
android:glEsVersion} attribute of the <a
@@ -133,17 +133,17 @@
</tr>
<tr>
<td>2.0</th>
-<td>89.4%</td>
+<td>87.0%</td>
</tr>
<tr>
<td>3.0</th>
-<td>10.5%</td>
+<td>12.9%</td>
</tr>
</table>
-<p style="clear:both"><em>Data collected during a 7-day period ending on April 1, 2014</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on May 1, 2014</em></p>
@@ -161,17 +161,17 @@
var VERSION_DATA =
[
{
- "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",
+ "chart": "//chart.googleapis.com/chart?chs=500x250&cht=p&chd=t%3A1.0%2C16.2%2C0.1%2C13.4%2C60.8%2C8.5&chf=bg%2Cs%2C00000000&chl=Froyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chco=c4df9b%2C6fad0c",
"data": [
{
"api": 8,
"name": "Froyo",
- "perc": "1.1"
+ "perc": "1.0"
},
{
"api": 10,
"name": "Gingerbread",
- "perc": "17.8"
+ "perc": "16.2"
},
{
"api": 13,
@@ -181,27 +181,27 @@
{
"api": 15,
"name": "Ice Cream Sandwich",
- "perc": "14.3"
+ "perc": "13.4"
},
{
"api": 16,
"name": "Jelly Bean",
- "perc": "34.4"
+ "perc": "33.5"
},
{
"api": 17,
"name": "Jelly Bean",
- "perc": "18.1"
+ "perc": "18.8"
},
{
"api": 18,
"name": "Jelly Bean",
- "perc": "8.9"
+ "perc": "8.5"
},
{
"api": 19,
"name": "KitKat",
- "perc": "5.3"
+ "perc": "8.5"
}
]
}
@@ -217,19 +217,19 @@
"data": {
"Large": {
"hdpi": "0.6",
- "ldpi": "0.7",
+ "ldpi": "0.6",
"mdpi": "4.4",
- "tvdpi": "1.5",
+ "tvdpi": "1.6",
"xhdpi": "0.6"
},
"Normal": {
- "hdpi": "33.7",
- "mdpi": "13.2",
- "xhdpi": "19.8",
- "xxhdpi": "12.5"
+ "hdpi": "33.9",
+ "mdpi": "12.5",
+ "xhdpi": "19.9",
+ "xxhdpi": "13.5"
},
"Small": {
- "ldpi": "8.1"
+ "ldpi": "7.5"
},
"Xlarge": {
"hdpi": "0.3",
@@ -238,8 +238,8 @@
"xhdpi": "0.3"
}
},
- "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"
+ "densitychart": "//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A8.2%2C21.1%2C1.6%2C34.8%2C20.8%2C13.5&chf=bg%2Cs%2C00000000&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chco=c4df9b%2C6fad0c",
+ "layoutchart": "//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A4.9%2C7.8%2C80.0%2C7.5&chf=bg%2Cs%2C00000000&chl=Xlarge%7CLarge%7CNormal%7CSmall&chco=c4df9b%2C6fad0c"
}
];
diff --git a/docs/html/guide/components/intents-common.jd b/docs/html/guide/components/intents-common.jd
index a0f7ce1..b4813a5 100644
--- a/docs/html/guide/components/intents-common.jd
+++ b/docs/html/guide/components/intents-common.jd
@@ -737,7 +737,7 @@
<pre>
public void editContact(Uri contactUri, String email) {
Intent intent = new Intent(Intent.ACTION_EDIT);
- intent.setDataAndType(contactUri, Contacts.CONTENT_TYPE);
+ intent.setData(contactUri);
intent.putExtra(Intents.Insert.EMAIL, email);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
diff --git a/docs/html/tools/device.jd b/docs/html/tools/device.jd
index ccd5903..e9caa44 100644
--- a/docs/html/tools/device.jd
+++ b/docs/html/tools/device.jd
@@ -192,6 +192,10 @@
<td><code>12d1</code></td>
</tr>
<tr>
+ <td>Intel</td>
+ <td><code>8087</code></td>
+ </tr>
+ <tr>
<td>K-Touch</td>
<td><code>24e3</code></td>
</tr>
diff --git a/graphics/java/android/graphics/CanvasProperty.java b/graphics/java/android/graphics/CanvasProperty.java
new file mode 100644
index 0000000..99ea9b1
--- /dev/null
+++ b/graphics/java/android/graphics/CanvasProperty.java
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+/**
+ * TODO: Make public?
+ * @hide
+ */
+public final class CanvasProperty<T> {
+ private long mNativeContainer;
+
+ public static CanvasProperty<Float> createFloat(float initialValue) {
+ return new CanvasProperty<Float>(nCreateFloat(initialValue));
+ }
+
+ public static CanvasProperty<Paint> createPaint(Paint initialValue) {
+ return new CanvasProperty<Paint>(nCreatePaint(initialValue.mNativePaint));
+ }
+
+ private CanvasProperty(long nativeContainer) {
+ mNativeContainer = nativeContainer;
+ }
+
+ /** @hide */
+ public long getNativeContainer() {
+ return mNativeContainer;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ nUnref(mNativeContainer);
+ mNativeContainer = 0;
+ } finally {
+ super.finalize();
+ }
+ }
+
+ private static native long nCreateFloat(float initialValue);
+ private static native long nCreatePaint(long initialValuePaintPtr);
+ private static native void nUnref(long ptr);
+}
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index e08ed50..062acaf 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -253,4 +253,31 @@
}
return -1;
}
+
+ /**
+ * Determine whether or not this is a public-visible {@code format}.
+ *
+ * <p>In particular, {@code @hide} formats will return {@code false}.</p>
+ *
+ * <p>Any other formats (including UNKNOWN) will return {@code false}.</p>
+ *
+ * @param format an integer format
+ * @return a boolean
+ *
+ * @hide
+ */
+ public static boolean isPublicFormat(int format) {
+ switch (format) {
+ case RGB_565:
+ case NV16:
+ case YUY2:
+ case YV12:
+ case NV21:
+ case YUV_420_888:
+ case RAW_SENSOR:
+ return true;
+ }
+
+ return false;
+ }
}
diff --git a/graphics/java/android/graphics/PixelFormat.java b/graphics/java/android/graphics/PixelFormat.java
index d96d6d8..832b9c3 100644
--- a/graphics/java/android/graphics/PixelFormat.java
+++ b/graphics/java/android/graphics/PixelFormat.java
@@ -115,7 +115,7 @@
info.bytesPerPixel = 1;
break;
default:
- throw new IllegalArgumentException("unkonwon pixel format " + format);
+ throw new IllegalArgumentException("unknown pixel format " + format);
}
}
@@ -135,4 +135,29 @@
public int bytesPerPixel;
public int bitsPerPixel;
+
+ /**
+ * Determine whether or not this is a public-visible and non-deprecated {@code format}.
+ *
+ * <p>In particular, {@code @hide} formats will return {@code false}.</p>
+ *
+ * <p>Any other indirect formats (such as {@code TRANSPARENT} or {@code TRANSLUCENT})
+ * will return {@code false}.</p>
+ *
+ * @param format an integer format
+ * @return a boolean
+ *
+ * @hide
+ */
+ public static boolean isPublicFormat(int format) {
+ switch (format) {
+ case RGBA_8888:
+ case RGBX_8888:
+ case RGB_888:
+ case RGB_565:
+ return true;
+ }
+
+ return false;
+ }
}
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index d877502..3f8c45c 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -62,9 +62,8 @@
* #updateTexImage} should not be called directly from the callback.
*/
public class SurfaceTexture {
-
- private EventHandler mEventHandler;
- private OnFrameAvailableListener mOnFrameAvailableListener;
+ private final Looper mCreatorLooper;
+ private Handler mOnFrameAvailableHandler;
/**
* These fields are used by native code, do not access or modify.
@@ -83,7 +82,8 @@
/**
* Exception thrown when a SurfaceTexture couldn't be created or resized.
*
- * @deprecated No longer thrown. {@link Surface.OutOfResourcesException} is used instead.
+ * @deprecated No longer thrown. {@link android.view.Surface.OutOfResourcesException}
+ * is used instead.
*/
@SuppressWarnings("serial")
@Deprecated
@@ -100,10 +100,10 @@
*
* @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
*
- * @throws OutOfResourcesException If the SurfaceTexture cannot be created.
+ * @throws Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
*/
public SurfaceTexture(int texName) {
- init(texName, false);
+ this(texName, false);
}
/**
@@ -121,20 +121,58 @@
* @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
* @param singleBufferMode whether the SurfaceTexture will be in single buffered mode.
*
- * @throws throws OutOfResourcesException If the SurfaceTexture cannot be created.
+ * @throws Surface.OutOfResourcesException If the SurfaceTexture cannot be created.
*/
public SurfaceTexture(int texName, boolean singleBufferMode) {
- init(texName, singleBufferMode);
+ mCreatorLooper = Looper.myLooper();
+ nativeInit(texName, singleBufferMode, new WeakReference<SurfaceTexture>(this));
}
/**
* Register a callback to be invoked when a new image frame becomes available to the
- * SurfaceTexture. Note that this callback may be called on an arbitrary thread, so it is not
+ * SurfaceTexture.
+ * <p>
+ * This callback may be called on an arbitrary thread, so it is not
* safe to call {@link #updateTexImage} without first binding the OpenGL ES context to the
* thread invoking the callback.
+ * </p>
+ *
+ * @param listener The listener to set.
*/
- public void setOnFrameAvailableListener(OnFrameAvailableListener l) {
- mOnFrameAvailableListener = l;
+ public void setOnFrameAvailableListener(OnFrameAvailableListener listener) {
+ setOnFrameAvailableListener(listener, null);
+ }
+
+ /**
+ * Register a callback to be invoked when a new image frame becomes available to the
+ * SurfaceTexture.
+ * <p>
+ * If no handler is specified, then this callback may be called on an arbitrary thread,
+ * so it is not safe to call {@link #updateTexImage} without first binding the OpenGL ES
+ * context to the thread invoking the callback.
+ * </p>
+ *
+ * @param listener The listener to set.
+ * @param handler The handler on which the listener should be invoked, or null
+ * to use an arbitrary thread.
+ */
+ public void setOnFrameAvailableListener(final OnFrameAvailableListener listener,
+ Handler handler) {
+ if (listener != null) {
+ // Although we claim the thread is arbitrary, earlier implementation would
+ // prefer to send the callback on the creating looper or the main looper
+ // so we preserve this behavior here.
+ Looper looper = handler != null ? handler.getLooper() :
+ mCreatorLooper != null ? mCreatorLooper : Looper.getMainLooper();
+ mOnFrameAvailableHandler = new Handler(looper, null, true /*async*/) {
+ @Override
+ public void handleMessage(Message msg) {
+ listener.onFrameAvailable(SurfaceTexture.this);
+ }
+ };
+ } else {
+ mOnFrameAvailableHandler = null;
+ }
}
/**
@@ -285,49 +323,22 @@
}
}
- private class EventHandler extends Handler {
- public EventHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- if (mOnFrameAvailableListener != null) {
- mOnFrameAvailableListener.onFrameAvailable(SurfaceTexture.this);
- }
- }
- }
-
/**
* This method is invoked from native code only.
*/
@SuppressWarnings({"UnusedDeclaration"})
- private static void postEventFromNative(Object selfRef) {
- WeakReference weakSelf = (WeakReference)selfRef;
- SurfaceTexture st = (SurfaceTexture)weakSelf.get();
- if (st == null) {
- return;
- }
-
- if (st.mEventHandler != null) {
- Message m = st.mEventHandler.obtainMessage();
- st.mEventHandler.sendMessage(m);
+ private static void postEventFromNative(WeakReference<SurfaceTexture> weakSelf) {
+ SurfaceTexture st = weakSelf.get();
+ if (st != null) {
+ Handler handler = st.mOnFrameAvailableHandler;
+ if (handler != null) {
+ handler.sendEmptyMessage(0);
+ }
}
}
- private void init(int texName, boolean singleBufferMode) throws Surface.OutOfResourcesException {
- Looper looper;
- if ((looper = Looper.myLooper()) != null) {
- mEventHandler = new EventHandler(looper);
- } else if ((looper = Looper.getMainLooper()) != null) {
- mEventHandler = new EventHandler(looper);
- } else {
- mEventHandler = null;
- }
- nativeInit(texName, singleBufferMode, new WeakReference<SurfaceTexture>(this));
- }
-
- private native void nativeInit(int texName, boolean singleBufferMode, Object weakSelf)
+ private native void nativeInit(int texName, boolean singleBufferMode,
+ WeakReference<SurfaceTexture> weakSelf)
throws Surface.OutOfResourcesException;
private native void nativeFinalize();
private native void nativeGetTransformMatrix(float[] mtx);
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index 3446000..218a057 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -299,7 +299,7 @@
*/
public void cancel() {
if (mInner != null) {
- mInner.end();
+ mInner.cancel();
}
if (mOuter != null) {
@@ -307,7 +307,7 @@
}
if (mAlpha != null) {
- mAlpha.end();
+ mAlpha.cancel();
}
}
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 0992717..77712b6 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -182,28 +182,14 @@
public VectorDrawable() {
mVectorState = new VectorDrawableState(null);
- mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 0);
-
- setDuration(DEFAULT_DURATION);
}
private VectorDrawable(VectorDrawableState state, Resources res, Theme theme) {
mVectorState = new VectorDrawableState(state);
- mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 0);
if (theme != null && canApplyTheme()) {
applyTheme(theme);
}
-
- long duration = mVectorState.mVAnimatedPath.getTotalAnimationDuration();
- if (duration == -1) {
- // If duration is infinite, set to 1 hour.
- // TODO: Define correct approach for infinite.
- duration = DEFAULT_INFINITE_DURATION;
- mVectorState.mBasicAnimator.setFloatValues(0, duration / 1000);
- mVectorState.mBasicAnimator.setInterpolator(new LinearInterpolator());
- }
- setDuration(duration);
}
@Override
@@ -212,118 +198,6 @@
}
@Override
- public void jumpToCurrentState() {
- stop();
- }
-
- /**
- * Starts the animation.
- */
- public void start() {
- mVectorState.mBasicAnimator.start();
- }
-
- /**
- * Stops the animation and moves to the end state.
- */
- public void stop() {
- mVectorState.mBasicAnimator.end();
- }
-
- /**
- * Returns the current completion value for the animation.
- *
- * @return the current point on the animation, typically between 0 and 1
- */
- public float geAnimationFraction() {
- return mVectorState.mVAnimatedPath.getValue();
- }
-
- /**
- * Set the current completion value for 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 ValueAnimator#INFINITE}.
- *
- * @param mode the animation mode, either {@link ValueAnimator#RESTART} or
- * {@link ValueAnimator#REVERSE}
- */
- 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 the animation repeat count, either a value greater than 0 or
- * {@link ValueAnimator#INFINITE}
- */
- public int getRepeatCount() {
- return mVectorState.mBasicAnimator.getRepeatCount();
- }
-
- @Override
- public boolean isStateful() {
- return true;
- }
-
- @Override
- protected boolean onStateChange(int[] state) {
- super.onStateChange(state);
-
- mVectorState.mVAnimatedPath.setState(state);
-
- final int direction = mVectorState.mVAnimatedPath.getTrigger(state);
- if (direction > 0) {
- animateForward();
- } else if (direction < 0) {
- animateBackward();
- }
-
- 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(1, 0);
- start();
- }
- }
-
- @Override
public void draw(Canvas canvas) {
final int saveCount = canvas.save();
final Rect bounds = getBounds();
@@ -432,7 +306,6 @@
final VectorDrawable drawable = new VectorDrawable();
drawable.inflate(resources, xpp, attrs);
- drawable.setAnimationFraction(0);
return drawable;
} catch (XmlPullParserException e) {
@@ -536,35 +409,10 @@
private void setAnimatedPath(VAnimatedPath animatedPath) {
mVectorState.mVAnimatedPath = animatedPath;
-
- 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 VectorDrawableState extends ConstantState {
int mChangingConfigurations;
- ValueAnimator mBasicAnimator;
VAnimatedPath mVAnimatedPath;
Rect mPadding;
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index d324439..eb0cac8 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -59,7 +59,8 @@
renderthread/DrawFrameTask.cpp \
renderthread/RenderProxy.cpp \
renderthread/RenderTask.cpp \
- renderthread/RenderThread.cpp
+ renderthread/RenderThread.cpp \
+ renderthread/TimeLord.cpp
intermediates := $(call intermediates-dir-for,STATIC_LIBRARIES,libRS,TARGET,)
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index ee16586..6a3003e 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -20,130 +20,13 @@
#include <set>
+#include "RenderNode.h"
#include "RenderProperties.h"
namespace android {
namespace uirenderer {
/************************************************************
- * Private header
- ************************************************************/
-
-typedef void (RenderProperties::*SetFloatProperty)(float value);
-typedef float (RenderProperties::*GetFloatProperty)() const;
-
-struct PropertyAccessors {
- GetFloatProperty getter;
- SetFloatProperty setter;
-};
-
-// Maps RenderProperty enum to accessors
-static const PropertyAccessors PROPERTY_ACCESSOR_LUT[] = {
- {&RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
- {&RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
- {&RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
- {&RenderProperties::getScaleX, &RenderProperties::setScaleX },
- {&RenderProperties::getScaleY, &RenderProperties::setScaleY },
- {&RenderProperties::getRotation, &RenderProperties::setRotation },
- {&RenderProperties::getRotationX, &RenderProperties::setRotationX },
- {&RenderProperties::getRotationY, &RenderProperties::setRotationY },
- {&RenderProperties::getX, &RenderProperties::setX },
- {&RenderProperties::getY, &RenderProperties::setY },
- {&RenderProperties::getZ, &RenderProperties::setZ },
- {&RenderProperties::getAlpha, &RenderProperties::setAlpha },
-};
-
-// Helper class to contain generic animator helpers
-class BaseAnimator {
-public:
- BaseAnimator();
- virtual ~BaseAnimator();
-
- void setInterpolator(Interpolator* interpolator);
- void setDuration(nsecs_t durationInMs);
-
- bool isFinished() { return mPlayState == FINISHED; }
-
-protected:
- // This is the main animation entrypoint that subclasses should call
- // to generate the onAnimation* lifecycle events
- // Returns true if the animation has finished, false otherwise
- bool animateFrame(nsecs_t frameTime);
-
- // Called when PlayState switches from PENDING to RUNNING
- virtual void onAnimationStarted() {}
- virtual void onAnimationUpdated(float fraction) = 0;
- virtual void onAnimationFinished() {}
-
-private:
- enum PlayState {
- PENDING,
- RUNNING,
- FINISHED,
- };
-
- Interpolator* mInterpolator;
- PlayState mPlayState;
- long mStartTime;
- long mDuration;
-};
-
-// Hide the base classes & private bits from the exported RenderPropertyAnimator
-// in this Impl class so that subclasses of RenderPropertyAnimator don't require
-// knowledge of the inner guts but only the public virtual methods.
-// Animates a single property
-class RenderPropertyAnimatorImpl : public BaseAnimator {
-public:
- RenderPropertyAnimatorImpl(GetFloatProperty getter, SetFloatProperty setter,
- RenderPropertyAnimator::DeltaValueType deltaType, float delta);
- ~RenderPropertyAnimatorImpl();
-
- bool animate(RenderProperties* target, TreeInfo& info);
-
-protected:
- virtual void onAnimationStarted();
- virtual void onAnimationUpdated(float fraction);
-
-private:
- // mTarget is only valid inside animate()
- RenderProperties* mTarget;
- GetFloatProperty mGetter;
- SetFloatProperty mSetter;
-
- RenderPropertyAnimator::DeltaValueType mDeltaValueType;
- float mDeltaValue;
- float mFromValue;
-};
-
-RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property,
- DeltaValueType deltaType, float deltaValue) {
- PropertyAccessors pa = PROPERTY_ACCESSOR_LUT[property];
- mImpl = new RenderPropertyAnimatorImpl(pa.getter, pa.setter, deltaType, deltaValue);
-}
-
-RenderPropertyAnimator::~RenderPropertyAnimator() {
- delete mImpl;
- mImpl = NULL;
-}
-
-void RenderPropertyAnimator::setInterpolator(Interpolator* interpolator) {
- mImpl->setInterpolator(interpolator);
-}
-
-void RenderPropertyAnimator::setDuration(nsecs_t durationInMs) {
- mImpl->setDuration(durationInMs);
-}
-
-bool RenderPropertyAnimator::isFinished() {
- return mImpl->isFinished();
-}
-
-bool RenderPropertyAnimator::animate(RenderProperties* target, TreeInfo& info) {
- return mImpl->animate(target, info);
-}
-
-
-/************************************************************
* Base animator
************************************************************/
@@ -168,10 +51,10 @@
mDuration = duration;
}
-bool BaseAnimator::animateFrame(nsecs_t frameTime) {
+bool BaseAnimator::animateFrame(TreeInfo& info) {
if (mPlayState == PENDING) {
mPlayState = RUNNING;
- mStartTime = frameTime;
+ mStartTime = info.frameTimeMs;
// No interpolator was set, use the default
if (!mInterpolator) {
setInterpolator(Interpolator::createDefaultInterpolator());
@@ -181,7 +64,7 @@
float fraction = 1.0f;
if (mPlayState == RUNNING) {
- fraction = mDuration > 0 ? (float)(frameTime - mStartTime) / mDuration : 1.0f;
+ fraction = mDuration > 0 ? (float)(info.frameTimeMs - mStartTime) / mDuration : 1.0f;
if (fraction >= 1.0f) {
fraction = 1.0f;
mPlayState = FINISHED;
@@ -192,48 +75,140 @@
if (mPlayState == FINISHED) {
onAnimationFinished();
+ callOnFinishedListener(info);
return true;
}
return false;
}
+void BaseAnimator::callOnFinishedListener(TreeInfo& info) {
+ if (mListener.get()) {
+ if (!info.animationHook) {
+ mListener->onAnimationFinished(this);
+ } else {
+ info.animationHook->callOnFinished(this, mListener.get());
+ }
+ }
+}
+
+/************************************************************
+ * BaseRenderNodeAnimator
+ ************************************************************/
+
+BaseRenderNodeAnimator::BaseRenderNodeAnimator(
+ BaseRenderNodeAnimator::DeltaValueType deltaType, float delta)
+ : mTarget(0)
+ , mDeltaValueType(deltaType)
+ , mDeltaValue(delta)
+ , mFromValue(-1) {
+}
+
+bool BaseRenderNodeAnimator::animate(RenderNode* target, TreeInfo& info) {
+ mTarget = target;
+ bool finished = animateFrame(info);
+ mTarget = NULL;
+ return finished;
+}
+
+void BaseRenderNodeAnimator::onAnimationStarted() {
+ mFromValue = getValue();
+
+ if (mDeltaValueType == BaseRenderNodeAnimator::ABSOLUTE) {
+ mDeltaValue = (mDeltaValue - mFromValue);
+ mDeltaValueType = BaseRenderNodeAnimator::DELTA;
+ }
+}
+
+void BaseRenderNodeAnimator::onAnimationUpdated(float fraction) {
+ float value = mFromValue + (mDeltaValue * fraction);
+ setValue(value);
+}
+
/************************************************************
* RenderPropertyAnimator
************************************************************/
-RenderPropertyAnimatorImpl::RenderPropertyAnimatorImpl(
- GetFloatProperty getter, SetFloatProperty setter,
- RenderPropertyAnimator::DeltaValueType deltaType, float delta)
- : mTarget(0)
- , mGetter(getter)
- , mSetter(setter)
- , mDeltaValueType(deltaType)
- , mDeltaValue(delta)
- , mFromValue(-1) {
+// Maps RenderProperty enum to accessors
+const RenderPropertyAnimator::PropertyAccessors RenderPropertyAnimator::PROPERTY_ACCESSOR_LUT[] = {
+ {&RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
+ {&RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
+ {&RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
+ {&RenderProperties::getScaleX, &RenderProperties::setScaleX },
+ {&RenderProperties::getScaleY, &RenderProperties::setScaleY },
+ {&RenderProperties::getRotation, &RenderProperties::setRotation },
+ {&RenderProperties::getRotationX, &RenderProperties::setRotationX },
+ {&RenderProperties::getRotationY, &RenderProperties::setRotationY },
+ {&RenderProperties::getX, &RenderProperties::setX },
+ {&RenderProperties::getY, &RenderProperties::setY },
+ {&RenderProperties::getZ, &RenderProperties::setZ },
+ {&RenderProperties::getAlpha, &RenderProperties::setAlpha },
+};
+
+RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property,
+ DeltaValueType deltaType, float deltaValue)
+ : BaseRenderNodeAnimator(deltaType, deltaValue)
+ , mPropertyAccess(PROPERTY_ACCESSOR_LUT[property]) {
}
-RenderPropertyAnimatorImpl::~RenderPropertyAnimatorImpl() {
+float RenderPropertyAnimator::getValue() const {
+ return (target()->animatorProperties().*mPropertyAccess.getter)();
}
-bool RenderPropertyAnimatorImpl::animate(RenderProperties* target, TreeInfo& info) {
- mTarget = target;
- bool finished = animateFrame(info.frameTimeMs);
- mTarget = NULL;
- return finished;
+void RenderPropertyAnimator::setValue(float value) {
+ (target()->animatorProperties().*mPropertyAccess.setter)(value);
}
-void RenderPropertyAnimatorImpl::onAnimationStarted() {
- mFromValue = (mTarget->*mGetter)();
+/************************************************************
+ * CanvasPropertyPrimitiveAnimator
+ ************************************************************/
- if (mDeltaValueType == RenderPropertyAnimator::ABSOLUTE) {
- mDeltaValue = (mDeltaValue - mFromValue);
- mDeltaValueType = RenderPropertyAnimator::DELTA;
+CanvasPropertyPrimitiveAnimator::CanvasPropertyPrimitiveAnimator(
+ CanvasPropertyPrimitive* property, DeltaValueType deltaType, float deltaValue)
+ : BaseRenderNodeAnimator(deltaType, deltaValue)
+ , mProperty(property) {
+}
+
+float CanvasPropertyPrimitiveAnimator::getValue() const {
+ return mProperty->value;
+}
+
+void CanvasPropertyPrimitiveAnimator::setValue(float value) {
+ mProperty->value = value;
+}
+
+/************************************************************
+ * CanvasPropertySkPaintAnimator
+ ************************************************************/
+
+CanvasPropertyPaintAnimator::CanvasPropertyPaintAnimator(
+ CanvasPropertyPaint* property, PaintField field,
+ DeltaValueType deltaType, float deltaValue)
+ : BaseRenderNodeAnimator(deltaType, deltaValue)
+ , mProperty(property)
+ , mField(field) {
+}
+
+float CanvasPropertyPaintAnimator::getValue() const {
+ switch (mField) {
+ case STROKE_WIDTH:
+ return mProperty->value.getStrokeWidth();
+ case ALPHA:
+ return mProperty->value.getAlpha();
}
+ LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
+ return -1;
}
-void RenderPropertyAnimatorImpl::onAnimationUpdated(float fraction) {
- float value = mFromValue + (mDeltaValue * fraction);
- (mTarget->*mSetter)(value);
+void CanvasPropertyPaintAnimator::setValue(float value) {
+ switch (mField) {
+ case STROKE_WIDTH:
+ mProperty->value.setStrokeWidth(value);
+ return;
+ case ALPHA:
+ mProperty->value.setAlpha(value);
+ return;
+ }
+ LOG_ALWAYS_FATAL("Unknown field %d", (int) mField);
}
} /* namespace uirenderer */
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
index 1c8361b..0b074cc 100644
--- a/libs/hwui/Animator.h
+++ b/libs/hwui/Animator.h
@@ -17,18 +17,72 @@
#define ANIMATOR_H
#include <cutils/compiler.h>
+#include <utils/StrongPointer.h>
+#include "CanvasProperty.h"
#include "Interpolator.h"
#include "TreeInfo.h"
+#include "utils/Macros.h"
#include "utils/VirtualLightRefBase.h"
namespace android {
namespace uirenderer {
+class RenderNode;
class RenderProperties;
-class RenderPropertyAnimatorImpl;
-class RenderPropertyAnimator : public VirtualLightRefBase {
+class AnimationListener : public VirtualLightRefBase {
+public:
+ ANDROID_API virtual void onAnimationFinished(BaseAnimator*) = 0;
+protected:
+ ANDROID_API virtual ~AnimationListener() {}
+};
+
+// Helper class to contain generic animator helpers
+class BaseAnimator : public VirtualLightRefBase {
+ PREVENT_COPY_AND_ASSIGN(BaseAnimator);
+public:
+
+ ANDROID_API void setInterpolator(Interpolator* interpolator);
+ ANDROID_API void setDuration(nsecs_t durationInMs);
+ ANDROID_API void setListener(AnimationListener* listener) {
+ mListener = listener;
+ }
+
+ bool isFinished() { return mPlayState == FINISHED; }
+
+protected:
+ BaseAnimator();
+ virtual ~BaseAnimator();
+
+ // This is the main animation entrypoint that subclasses should call
+ // to generate the onAnimation* lifecycle events
+ // Returns true if the animation has finished, false otherwise
+ bool animateFrame(TreeInfo& info);
+
+ // Called when PlayState switches from PENDING to RUNNING
+ virtual void onAnimationStarted() {}
+ virtual void onAnimationUpdated(float fraction) = 0;
+ virtual void onAnimationFinished() {}
+
+private:
+ void callOnFinishedListener(TreeInfo& info);
+
+ enum PlayState {
+ PENDING,
+ RUNNING,
+ FINISHED,
+ };
+
+ Interpolator* mInterpolator;
+ PlayState mPlayState;
+ long mStartTime;
+ long mDuration;
+
+ sp<AnimationListener> mListener;
+};
+
+class BaseRenderNodeAnimator : public BaseAnimator {
public:
// Since the UI thread doesn't necessarily know what the current values
// actually are and thus can't do the calculations, this is used to inform
@@ -43,6 +97,29 @@
DELTA,
};
+ bool animate(RenderNode* target, TreeInfo& info);
+
+protected:
+ BaseRenderNodeAnimator(DeltaValueType deltaType, float deltaValue);
+
+ RenderNode* target() const { return mTarget; }
+ virtual float getValue() const = 0;
+ virtual void setValue(float value) = 0;
+
+private:
+ virtual void onAnimationStarted();
+ virtual void onAnimationUpdated(float fraction);
+
+ // mTarget is only valid inside animate()
+ RenderNode* mTarget;
+
+ BaseRenderNodeAnimator::DeltaValueType mDeltaValueType;
+ float mDeltaValue;
+ float mFromValue;
+};
+
+class RenderPropertyAnimator : public BaseRenderNodeAnimator {
+public:
enum RenderProperty {
TRANSLATION_X = 0,
TRANSLATION_Y,
@@ -58,19 +135,53 @@
ALPHA,
};
- ANDROID_API void setInterpolator(Interpolator* interpolator);
- ANDROID_API void setDuration(nsecs_t durationInMs);
- ANDROID_API bool isFinished();
-
- bool animate(RenderProperties* target, TreeInfo& info);
+ ANDROID_API RenderPropertyAnimator(RenderProperty property,
+ DeltaValueType deltaType, float deltaValue);
protected:
- ANDROID_API RenderPropertyAnimator(RenderProperty property, DeltaValueType deltaType,
- float deltaValue);
- ANDROID_API virtual ~RenderPropertyAnimator();
+ ANDROID_API virtual float getValue() const;
+ ANDROID_API virtual void setValue(float value);
private:
- RenderPropertyAnimatorImpl* mImpl;
+ typedef void (RenderProperties::*SetFloatProperty)(float value);
+ typedef float (RenderProperties::*GetFloatProperty)() const;
+
+ struct PropertyAccessors {
+ GetFloatProperty getter;
+ SetFloatProperty setter;
+ };
+
+ PropertyAccessors mPropertyAccess;
+
+ static const PropertyAccessors PROPERTY_ACCESSOR_LUT[];
+};
+
+class CanvasPropertyPrimitiveAnimator : public BaseRenderNodeAnimator {
+public:
+ ANDROID_API CanvasPropertyPrimitiveAnimator(CanvasPropertyPrimitive* property,
+ DeltaValueType deltaType, float deltaValue);
+protected:
+ ANDROID_API virtual float getValue() const;
+ ANDROID_API virtual void setValue(float value);
+private:
+ sp<CanvasPropertyPrimitive> mProperty;
+};
+
+class CanvasPropertyPaintAnimator : public BaseRenderNodeAnimator {
+public:
+ enum PaintField {
+ STROKE_WIDTH = 0,
+ ALPHA,
+ };
+
+ ANDROID_API CanvasPropertyPaintAnimator(CanvasPropertyPaint* property,
+ PaintField field, DeltaValueType deltaType, float deltaValue);
+protected:
+ ANDROID_API virtual float getValue() const;
+ ANDROID_API virtual void setValue(float value);
+private:
+ sp<CanvasPropertyPaint> mProperty;
+ PaintField mField;
};
} /* namespace uirenderer */
diff --git a/libs/hwui/CanvasProperty.h b/libs/hwui/CanvasProperty.h
new file mode 100644
index 0000000..2e1d176
--- /dev/null
+++ b/libs/hwui/CanvasProperty.h
@@ -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.
+ */
+#ifndef CANVASPROPERTY_H
+#define CANVASPROPERTY_H
+
+#include "utils/Macros.h"
+#include "utils/VirtualLightRefBase.h"
+
+#include <SkPaint.h>
+
+namespace android {
+namespace uirenderer {
+
+class CanvasPropertyPrimitive : public VirtualLightRefBase {
+ PREVENT_COPY_AND_ASSIGN(CanvasPropertyPrimitive);
+public:
+ CanvasPropertyPrimitive(float initialValue) : value(initialValue) {}
+
+ float value;
+};
+
+class CanvasPropertyPaint : public VirtualLightRefBase {
+ PREVENT_COPY_AND_ASSIGN(CanvasPropertyPaint);
+public:
+ CanvasPropertyPaint(const SkPaint& initialValue) : value(initialValue) {}
+
+ SkPaint value;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* CANVASPROPERTY_H */
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index fe70d13..eaeb772 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -140,6 +140,14 @@
void addChild(DrawDisplayListOp* childOp);
const Vector<DrawDisplayListOp*>& children() { return mChildren; }
+ void refProperty(CanvasPropertyPrimitive* prop) {
+ mReferenceHolders.push(prop);
+ }
+
+ void refProperty(CanvasPropertyPaint* prop) {
+ mReferenceHolders.push(prop);
+ }
+
private:
Vector< sp<VirtualLightRefBase> > mReferenceHolders;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 6dfb918..ce92beb 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1198,6 +1198,27 @@
float mRadius;
};
+class DrawCirclePropsOp : public DrawOp {
+public:
+ DrawCirclePropsOp(float* x, float* y, float* radius, const SkPaint* paint)
+ : DrawOp(paint), mX(x), mY(y), mRadius(radius) {}
+
+ virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
+ return renderer.drawCircle(*mX, *mY, *mRadius, getPaint(renderer));
+ }
+
+ virtual void output(int level, uint32_t logFlags) const {
+ OP_LOG("Draw Circle Props x %p, y %p, r %p", mX, mY, mRadius);
+ }
+
+ virtual const char* name() { return "DrawCircleProps"; }
+
+private:
+ float* mX;
+ float* mY;
+ float* mRadius;
+};
+
class DrawOvalOp : public DrawStrokableOp {
public:
DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index e36d975..8afd106 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -299,6 +299,17 @@
return DrawGlInfo::kStatusDone;
}
+status_t DisplayListRenderer::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+ CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
+ mDisplayListData->refProperty(x);
+ mDisplayListData->refProperty(y);
+ mDisplayListData->refProperty(radius);
+ mDisplayListData->refProperty(paint);
+ addDrawOp(new (alloc()) DrawCirclePropsOp(&x->value, &y->value,
+ &radius->value, &paint->value));
+ return DrawGlInfo::kStatusDone;
+}
+
status_t DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
const SkPaint* paint) {
paint = refPaint(paint);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 04c5a73..25e78c1 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -135,6 +135,8 @@
virtual status_t drawRoundRect(float left, float top, float right, float bottom,
float rx, float ry, const SkPaint* paint);
virtual status_t drawCircle(float x, float y, float radius, const SkPaint* paint);
+ virtual status_t drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+ CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint);
virtual status_t drawOval(float left, float top, float right, float bottom,
const SkPaint* paint);
virtual status_t drawArc(float left, float top, float right, float bottom,
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index b52003c..647c281 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -737,30 +737,34 @@
// a null path is OK because there are no custom kernels used
// hence nothing gets cached by RS
if (!mRs->init("", RSC::RS_INIT_LOW_LATENCY | RSC::RS_INIT_SYNCHRONOUS)) {
+ mRs.clear();
ALOGE("blur RS failed to init");
+ } else {
+ mRsElement = RSC::Element::A_8(mRs);
+ mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement);
}
-
- mRsElement = RSC::Element::A_8(mRs);
- mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement);
}
+ if (mRs != 0) {
+ RSC::sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0);
+ RSC::sp<RSC::Allocation> ain = RSC::Allocation::createTyped(mRs, t,
+ RS_ALLOCATION_MIPMAP_NONE,
+ RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
+ *image);
+ RSC::sp<RSC::Allocation> aout = RSC::Allocation::createTyped(mRs, t,
+ RS_ALLOCATION_MIPMAP_NONE,
+ RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
+ outImage);
- RSC::sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0);
- RSC::sp<RSC::Allocation> ain = RSC::Allocation::createTyped(mRs, t,
- RS_ALLOCATION_MIPMAP_NONE, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
- *image);
- RSC::sp<RSC::Allocation> aout = RSC::Allocation::createTyped(mRs, t,
- RS_ALLOCATION_MIPMAP_NONE, RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
- outImage);
+ mRsScript->setRadius(radius);
+ mRsScript->setInput(ain);
+ mRsScript->forEach(aout);
- mRsScript->setRadius(radius);
- mRsScript->setInput(ain);
- mRsScript->forEach(aout);
+ // replace the original image's pointer, avoiding a copy back to the original buffer
+ free(*image);
+ *image = outImage;
- // replace the original image's pointer, avoiding a copy back to the original buffer
- free(*image);
- *image = outImage;
-
- return;
+ return;
+ }
}
#endif
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index b49d1e1..7794abc 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -49,6 +49,7 @@
#include "UvMapper.h"
#include "Vertex.h"
#include "Caches.h"
+#include "CanvasProperty.h"
namespace android {
namespace uirenderer {
@@ -200,6 +201,12 @@
virtual status_t drawRoundRect(float left, float top, float right, float bottom,
float rx, float ry, const SkPaint* paint);
virtual status_t drawCircle(float x, float y, float radius, const SkPaint* paint);
+ virtual status_t drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y,
+ CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) {
+ // TODO: Remove once android_view_GLES20Canvas uses DisplayListRenderer
+ // directly
+ return drawCircle(x->value, y->value, radius->value, &paint->value);
+ }
virtual status_t drawOval(float left, float top, float right, float bottom,
const SkPaint* paint);
virtual status_t drawArc(float left, float top, float right, float bottom,
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 7a9c181..9902ff1 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -109,7 +109,7 @@
prepareSubTree(info, mDisplayListData);
}
-static bool is_finished(const sp<RenderPropertyAnimator>& animator) {
+static bool is_finished(const sp<BaseRenderNodeAnimator>& animator) {
return animator->isFinished();
}
@@ -120,7 +120,7 @@
}
if (mNeedsAnimatorsSync) {
mAnimators.resize(mStagingAnimators.size());
- std::vector< sp<RenderPropertyAnimator> >::iterator it;
+ std::vector< sp<BaseRenderNodeAnimator> >::iterator it;
// hint: this means copy_if_not()
it = std::remove_copy_if(mStagingAnimators.begin(), mStagingAnimators.end(),
mAnimators.begin(), is_finished);
@@ -141,36 +141,32 @@
class AnimateFunctor {
public:
- AnimateFunctor(RenderProperties* target, TreeInfo& info)
+ AnimateFunctor(RenderNode* target, TreeInfo& info)
: mTarget(target), mInfo(info) {}
- bool operator() (sp<RenderPropertyAnimator>& animator) {
- bool finished = animator->animate(mTarget, mInfo);
- if (finished && mInfo.animationListener) {
- mInfo.animationListener->onAnimationFinished(animator);
- }
- return finished;
+ bool operator() (sp<BaseRenderNodeAnimator>& animator) {
+ return animator->animate(mTarget, mInfo);
}
private:
- RenderProperties* mTarget;
+ RenderNode* mTarget;
TreeInfo& mInfo;
};
void RenderNode::evaluateAnimations(TreeInfo& info) {
if (!mAnimators.size()) return;
- AnimateFunctor functor(&mProperties, info);
- std::vector< sp<RenderPropertyAnimator> >::iterator newEnd;
+ AnimateFunctor functor(this, info);
+ std::vector< sp<BaseRenderNodeAnimator> >::iterator newEnd;
newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
mAnimators.erase(newEnd, mAnimators.end());
mProperties.updateMatrix();
- info.hasAnimations |= mAnimators.size();
+ info.out.hasAnimations |= mAnimators.size();
}
void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) {
if (subtree) {
TextureCache& cache = Caches::getInstance().textureCache;
- info.hasFunctors |= subtree->functorCount;
+ info.out.hasFunctors |= subtree->functorCount;
// TODO: Fix ownedBitmapResources to not require disabling prepareTextures
// and thus falling out of async drawing path.
if (subtree->ownedBitmapResources.size()) {
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 294f436..159903c 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -128,6 +128,10 @@
return mProperties;
}
+ RenderProperties& animatorProperties() {
+ return mProperties;
+ }
+
const RenderProperties& stagingProperties() {
return mStagingProperties;
}
@@ -148,13 +152,13 @@
ANDROID_API virtual void prepareTree(TreeInfo& info);
// UI thread only!
- ANDROID_API void addAnimator(const sp<RenderPropertyAnimator>& animator) {
+ ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator) {
mStagingAnimators.insert(animator);
mNeedsAnimatorsSync = true;
}
// UI thread only!
- ANDROID_API void removeAnimator(const sp<RenderPropertyAnimator>& animator) {
+ ANDROID_API void removeAnimator(const sp<BaseRenderNodeAnimator>& animator) {
mStagingAnimators.erase(animator);
mNeedsAnimatorsSync = true;
}
@@ -233,8 +237,8 @@
DisplayListData* mStagingDisplayListData;
bool mNeedsAnimatorsSync;
- std::set< sp<RenderPropertyAnimator> > mStagingAnimators;
- std::vector< sp<RenderPropertyAnimator> > mAnimators;
+ std::set< sp<BaseRenderNodeAnimator> > mStagingAnimators;
+ std::vector< sp<BaseRenderNodeAnimator> > mAnimators;
/**
* Draw time state - these properties are only set and used during rendering
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 8957607..fc5994c 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -16,44 +16,51 @@
#ifndef TREEINFO_H
#define TREEINFO_H
-#include <cutils/compiler.h>
#include <utils/Timers.h>
-#include <utils/StrongPointer.h>
namespace android {
namespace uirenderer {
-class RenderPropertyAnimator;
+class BaseAnimator;
+class AnimationListener;
-class AnimationListener {
+class AnimationHook {
public:
- ANDROID_API virtual void onAnimationFinished(const sp<RenderPropertyAnimator>&) = 0;
+ virtual void callOnFinished(BaseAnimator* animator, AnimationListener* listener) = 0;
protected:
- ANDROID_API virtual ~AnimationListener() {}
+ ~AnimationHook() {}
};
struct TreeInfo {
// The defaults here should be safe for everyone but DrawFrameTask to use as-is.
TreeInfo()
- : hasFunctors(false)
- , prepareTextures(false)
- , performStagingPush(true)
- , frameTimeMs(0)
- , evaluateAnimations(false)
- , hasAnimations(false)
- , animationListener(0)
+ : frameTimeMs(0)
+ , animationHook(NULL)
+ , prepareTextures(false)
+ , performStagingPush(true)
+ , evaluateAnimations(false)
{}
- bool hasFunctors;
+ nsecs_t frameTimeMs;
+ AnimationHook* animationHook;
bool prepareTextures;
bool performStagingPush;
-
- // Animations
- nsecs_t frameTimeMs;
bool evaluateAnimations;
- // This is only updated if evaluateAnimations is true
- bool hasAnimations;
- AnimationListener* animationListener;
+
+ struct Out {
+ Out()
+ : hasFunctors(false)
+ , hasAnimations(false)
+ , requiresUiRedraw(false)
+ {}
+ bool hasFunctors;
+ // This is only updated if evaluateAnimations is true
+ bool hasAnimations;
+ // This is set to true if there is an animation that RenderThread cannot
+ // animate itself, such as if hasFunctors is true
+ // This is only set if hasAnimations is true
+ bool requiresUiRedraw;
+ } out;
// TODO: Damage calculations
};
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 63f4b95..fc3548c 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -391,10 +391,20 @@
mHaveNewSurface |= mGlobalContext->makeCurrent(mEglSurface);
}
+void CanvasContext::prepareDraw(const Vector<DeferredLayerUpdater*>* layerUpdaters,
+ TreeInfo& info) {
+ LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot prepareDraw without a canvas!");
+ makeCurrent();
+
+ processLayerUpdates(layerUpdaters, info);
+ if (info.out.hasAnimations) {
+ // TODO: Uh... crap?
+ }
+ prepareTree(info);
+}
+
void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters,
TreeInfo& info) {
- LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot process layer updates without a canvas!");
- makeCurrent();
for (size_t i = 0; i < layerUpdaters->size(); i++) {
DeferredLayerUpdater* update = layerUpdaters->itemAt(i);
bool success = update->apply(info);
@@ -406,11 +416,19 @@
}
void CanvasContext::prepareTree(TreeInfo& info) {
+ mRenderThread.removeFrameCallback(this);
+
+ info.frameTimeMs = mRenderThread.timeLord().frameTimeMs();
mRootRenderNode->prepareTree(info);
- if (info.hasAnimations && !info.hasFunctors) {
- // TODO: Functors
- mRenderThread.postFrameCallback(this);
+ if (info.out.hasAnimations) {
+ if (info.out.hasFunctors) {
+ info.out.requiresUiRedraw = true;
+ } else if (!info.out.requiresUiRedraw) {
+ // If animationsNeedsRedraw is set don't bother posting for an RT anim
+ // as we will just end up fighting the UI thread.
+ mRenderThread.postFrameCallback(this);
+ }
}
}
@@ -449,12 +467,11 @@
}
// Called by choreographer to do an RT-driven animation
-void CanvasContext::doFrame(nsecs_t frameTimeNanos) {
+void CanvasContext::doFrame() {
ATRACE_CALL();
TreeInfo info;
info.evaluateAnimations = true;
- info.frameTimeMs = nanoseconds_to_milliseconds(frameTimeNanos);
info.performStagingPush = false;
info.prepareTextures = false;
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 0873ad4..a95e27a 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -53,13 +53,12 @@
void pauseSurface(EGLNativeWindowType window);
void setup(int width, int height);
void makeCurrent();
- void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info);
- void prepareTree(TreeInfo& info);
+ void prepareDraw(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info);
void draw(Rect* dirty);
void destroyCanvasAndSurface();
// IFrameCallback, Chroreographer-driven frame callback entry point
- virtual void doFrame(nsecs_t frameTimeNanos);
+ virtual void doFrame();
bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
@@ -71,6 +70,9 @@
Layer* createTextureLayer();
private:
+ void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info);
+ void prepareTree(TreeInfo& info);
+
void setSurface(EGLNativeWindowType window);
void swapBuffers();
void requireSurface();
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index ff4be71..3b8786c 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -30,13 +30,18 @@
namespace uirenderer {
namespace renderthread {
-DrawFrameTask::DrawFrameTask() : mContext(0) {
+DrawFrameTask::DrawFrameTask()
+ : mRenderThread(NULL)
+ , mContext(NULL)
+ , mFrameTimeNanos(0)
+ , mSyncResult(kSync_OK) {
}
DrawFrameTask::~DrawFrameTask() {
}
-void DrawFrameTask::setContext(CanvasContext* context) {
+void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context) {
+ mRenderThread = thread;
mContext = context;
}
@@ -59,18 +64,23 @@
mDirty.set(left, top, right, bottom);
}
-void DrawFrameTask::drawFrame(RenderThread* renderThread) {
+int DrawFrameTask::drawFrame(nsecs_t frameTimeNanos) {
LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
- postAndWait(renderThread);
+ mSyncResult = kSync_OK;
+ mFrameTimeNanos = frameTimeNanos;
+ postAndWait();
// Reset the single-frame data
+ mFrameTimeNanos = 0;
mDirty.setEmpty();
+
+ return mSyncResult;
}
-void DrawFrameTask::postAndWait(RenderThread* renderThread) {
+void DrawFrameTask::postAndWait() {
AutoMutex _lock(mLock);
- renderThread->queue(this);
+ mRenderThread->queue(this);
mSignal.wait(mLock);
}
@@ -99,21 +109,25 @@
info.prepareTextures = true;
info.performStagingPush = true;
info.evaluateAnimations = true;
- // TODO: Get this from Choreographer
- nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
- info.frameTimeMs = nanoseconds_to_milliseconds(frameTimeNs);
}
bool DrawFrameTask::syncFrameState() {
ATRACE_CALL();
+ mRenderThread->timeLord().vsyncReceived(mFrameTimeNanos);
mContext->makeCurrent();
Caches::getInstance().textureCache.resetMarkInUse();
TreeInfo info;
initTreeInfo(info);
- mContext->processLayerUpdates(&mLayers, info);
- mContext->prepareTree(info);
+ mContext->prepareDraw(&mLayers, info);
+ if (info.out.hasAnimations) {
+ // TODO: dirty calculations, for now just do a full-screen inval
+ mDirty.setEmpty();
+ if (info.out.requiresUiRedraw) {
+ mSyncResult |= kSync_UIRedrawRequired;
+ }
+ }
// If prepareTextures is false, we ran out of texture cache space
- return !info.hasFunctors && info.prepareTextures;
+ return !info.out.hasFunctors && info.prepareTextures;
}
void DrawFrameTask::unblockUiThread() {
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index c280868..b9307e1 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -37,6 +37,11 @@
class CanvasContext;
class RenderThread;
+enum SyncResult {
+ kSync_OK = 0,
+ kSync_UIRedrawRequired = 1 << 1,
+};
+
/*
* 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
@@ -48,30 +53,34 @@
DrawFrameTask();
virtual ~DrawFrameTask();
- void setContext(CanvasContext* context);
+ void setContext(RenderThread* thread, CanvasContext* context);
void addLayer(DeferredLayerUpdater* layer);
void removeLayer(DeferredLayerUpdater* layer);
void setDirty(int left, int top, int right, int bottom);
- void drawFrame(RenderThread* renderThread);
+ int drawFrame(nsecs_t frameTimeNanos);
virtual void run();
private:
- void postAndWait(RenderThread* renderThread);
+ void postAndWait();
bool syncFrameState();
void unblockUiThread();
Mutex mLock;
Condition mSignal;
+ RenderThread* mRenderThread;
CanvasContext* mContext;
/*********************************************
* Single frame data
*********************************************/
Rect mDirty;
+ nsecs_t mFrameTimeNanos;
+
+ int mSyncResult;
/*********************************************
* Multi frame data
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 87886e6..c2806fa 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -62,7 +62,7 @@
args->translucent = translucent;
args->rootRenderNode = rootRenderNode;
mContext = (CanvasContext*) postAndWait(task);
- mDrawFrameTask.setContext(mContext);
+ mDrawFrameTask.setContext(&mRenderThread, mContext);
}
RenderProxy::~RenderProxy() {
@@ -79,13 +79,38 @@
SETUP_TASK(destroyContext);
args->context = mContext;
mContext = 0;
- mDrawFrameTask.setContext(0);
+ mDrawFrameTask.setContext(NULL, NULL);
// 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);
}
}
+CREATE_BRIDGE2(setFrameInterval, RenderThread* thread, nsecs_t frameIntervalNanos) {
+ args->thread->timeLord().setFrameInterval(args->frameIntervalNanos);
+ return NULL;
+}
+
+void RenderProxy::setFrameInterval(nsecs_t frameIntervalNanos) {
+ SETUP_TASK(setFrameInterval);
+ args->thread = &mRenderThread;
+ args->frameIntervalNanos = frameIntervalNanos;
+ post(task);
+}
+
+CREATE_BRIDGE0(loadSystemProperties) {
+ bool needsRedraw = false;
+ if (Caches::hasInstance()) {
+ needsRedraw = Caches::getInstance().initProperties();
+ }
+ return (void*) needsRedraw;
+}
+
+bool RenderProxy::loadSystemProperties() {
+ SETUP_TASK(loadSystemProperties);
+ return (bool) postAndWait(task);
+}
+
CREATE_BRIDGE2(initialize, CanvasContext* context, EGLNativeWindowType window) {
return (void*) args->context->initialize(args->window);
}
@@ -134,10 +159,10 @@
post(task);
}
-void RenderProxy::syncAndDrawFrame(
+int RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos,
int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom) {
mDrawFrameTask.setDirty(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
- mDrawFrameTask.drawFrame(&mRenderThread);
+ return mDrawFrameTask.drawFrame(frameTimeNanos);
}
CREATE_BRIDGE1(destroyCanvasAndSurface, CanvasContext* context) {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index eab1395..013c3bd 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -25,6 +25,7 @@
#include <utils/Condition.h>
#include <utils/Functor.h>
#include <utils/Mutex.h>
+#include <utils/Timers.h>
#include <utils/StrongPointer.h>
#include <utils/Vector.h>
@@ -59,11 +60,14 @@
ANDROID_API RenderProxy(bool translucent, RenderNode* rootNode);
ANDROID_API virtual ~RenderProxy();
+ ANDROID_API void setFrameInterval(nsecs_t frameIntervalNanos);
+ ANDROID_API bool loadSystemProperties();
+
ANDROID_API bool initialize(const sp<ANativeWindow>& window);
ANDROID_API void updateSurface(const sp<ANativeWindow>& window);
ANDROID_API void pauseSurface(const sp<ANativeWindow>& window);
ANDROID_API void setup(int width, int height);
- ANDROID_API void syncAndDrawFrame(
+ ANDROID_API int syncAndDrawFrame(nsecs_t frameTimeNanos,
int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
ANDROID_API void destroyCanvasAndSurface();
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index e95707a..35a3eab 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -129,8 +129,7 @@
, mDisplayEventReceiver(0)
, mVsyncRequested(false)
, mFrameCallbackTaskPending(false)
- , mFrameCallbackTask(0)
- , mFrameTime(0) {
+ , mFrameCallbackTask(0) {
mFrameCallbackTask = new DispatchFrameCallbacks(this);
mLooper = new Looper(false);
run("RenderThread");
@@ -193,7 +192,7 @@
nsecs_t vsyncEvent = latestVsyncEvent(mDisplayEventReceiver);
if (vsyncEvent > 0) {
mVsyncRequested = false;
- mFrameTime = vsyncEvent;
+ mTimeLord.vsyncReceived(vsyncEvent);
if (!mFrameCallbackTaskPending) {
mFrameCallbackTaskPending = true;
//queueDelayed(mFrameCallbackTask, DISPATCH_FRAME_CALLBACKS_DELAY);
@@ -209,7 +208,7 @@
mFrameCallbacks.swap(callbacks);
for (std::set<IFrameCallback*>::iterator it = callbacks.begin(); it != callbacks.end(); it++) {
- (*it)->doFrame(mFrameTime);
+ (*it)->doFrame();
}
}
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index b93dfd6..215d294 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -28,6 +28,8 @@
#include <utils/Singleton.h>
#include <utils/Thread.h>
+#include "TimeLord.h"
+
namespace android {
class DisplayEventReceiver;
@@ -53,7 +55,7 @@
// Mimics android.view.Choreographer.FrameCallback
class IFrameCallback {
public:
- virtual void doFrame(nsecs_t frameTimeNanos) = 0;
+ virtual void doFrame() = 0;
protected:
~IFrameCallback() {}
@@ -71,6 +73,8 @@
void postFrameCallback(IFrameCallback* callback);
void removeFrameCallback(IFrameCallback* callback);
+ TimeLord& timeLord() { return mTimeLord; }
+
protected:
virtual bool threadLoop();
@@ -102,7 +106,8 @@
std::set<IFrameCallback*> mFrameCallbacks;
bool mFrameCallbackTaskPending;
DispatchFrameCallbacks* mFrameCallbackTask;
- nsecs_t mFrameTime;
+
+ TimeLord mTimeLord;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp
new file mode 100644
index 0000000..758d96e
--- /dev/null
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -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.
+ */
+#include "TimeLord.h"
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+TimeLord::TimeLord()
+ : mFrameIntervalNanos(0)
+ , mFrameTimeNanos(0) {
+}
+
+void TimeLord::vsyncReceived(nsecs_t vsync) {
+ if (vsync > mFrameTimeNanos) {
+ mFrameTimeNanos = vsync;
+ }
+}
+
+nsecs_t TimeLord::frameTimeMs() {
+ // Logic copied from Choreographer.java
+ nsecs_t now = systemTime(CLOCK_MONOTONIC);
+ nsecs_t jitterNanos = now - mFrameTimeNanos;
+ if (jitterNanos >= mFrameIntervalNanos) {
+ nsecs_t lastFrameOffset = jitterNanos % mFrameIntervalNanos;
+ mFrameTimeNanos = now - lastFrameOffset;
+ }
+ return nanoseconds_to_milliseconds(mFrameTimeNanos);
+}
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/TimeLord.h b/libs/hwui/renderthread/TimeLord.h
new file mode 100644
index 0000000..52c6d9e
--- /dev/null
+++ b/libs/hwui/renderthread/TimeLord.h
@@ -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.
+ */
+#ifndef TIMELORD_H
+#define TIMELORD_H
+
+#include <utils/Timers.h>
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+class RenderThread;
+
+// This class serves as a helper to filter & manage frame times from multiple sources
+// ensuring that time flows linearly and smoothly
+class TimeLord {
+public:
+ void setFrameInterval(nsecs_t intervalNanos) { mFrameIntervalNanos = intervalNanos; }
+ void vsyncReceived(nsecs_t vsync);
+ nsecs_t frameTimeMs();
+
+private:
+ friend class RenderThread;
+
+ TimeLord();
+ ~TimeLord() {}
+
+ nsecs_t mFrameIntervalNanos;
+ nsecs_t mFrameTimeNanos;
+};
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* TIMELORD_H */
diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h
new file mode 100644
index 0000000..14a3ec0
--- /dev/null
+++ b/libs/hwui/utils/Macros.h
@@ -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.
+ */
+#ifndef MACROS_H
+#define MACROS_H
+
+#define PREVENT_COPY_AND_ASSIGN(Type) \
+ private: \
+ Type(const Type&); \
+ void operator=(const Type&)
+
+
+#endif /* MACROS_H */
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index ad0d459..6b2a247 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -32,11 +32,13 @@
/** Default audio data format */
public static final int ENCODING_DEFAULT = 1;
- // These two values must be kept in sync with core/jni/android_media_AudioFormat.h
+ // These values must be kept in sync with core/jni/android_media_AudioFormat.h
/** Audio data format: PCM 16 bit per sample. Guaranteed to be supported by devices. */
public static final int ENCODING_PCM_16BIT = 2;
/** Audio data format: PCM 8 bit per sample. Not guaranteed to be supported by devices. */
public static final int ENCODING_PCM_8BIT = 3;
+ /** @hide Candidate for public API */
+ public static final int ENCODING_PCM_FLOAT = 4;
/** Invalid audio channel configuration */
/** @deprecated use CHANNEL_INVALID instead */
@@ -139,4 +141,19 @@
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
+ /** @hide */
+ public static int getBytesPerSample(int audioFormat)
+ {
+ switch (audioFormat) {
+ case ENCODING_PCM_8BIT:
+ return 1;
+ case ENCODING_PCM_16BIT:
+ case ENCODING_DEFAULT:
+ return 2;
+ case ENCODING_INVALID:
+ default:
+ throw new IllegalArgumentException("Bad audio format " + audioFormat);
+ }
+ }
+
}
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index a4891f8..384e120 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -319,7 +319,7 @@
// NB: this section is only valid with PCM data.
// To update when supporting compressed formats
int frameSizeInBytes = mChannelCount
- * (mAudioFormat == AudioFormat.ENCODING_PCM_8BIT ? 1 : 2);
+ * (AudioFormat.getBytesPerSample(mAudioFormat));
if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) {
throw new IllegalArgumentException("Invalid audio buffer size.");
}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 17840f2..1899685 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -518,7 +518,7 @@
// NB: this section is only valid with PCM data.
// To update when supporting compressed formats
int frameSizeInBytes = mChannelCount
- * (mAudioFormat == AudioFormat.ENCODING_PCM_8BIT ? 1 : 2);
+ * (AudioFormat.getBytesPerSample(mAudioFormat));
if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) {
throw new IllegalArgumentException("Invalid audio buffer size.");
}
diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java
index bd91fc5..7735e78 100644
--- a/media/java/android/media/JetPlayer.java
+++ b/media/java/android/media/JetPlayer.java
@@ -169,9 +169,11 @@
native_setup(new WeakReference<JetPlayer>(this),
JetPlayer.getMaxTracks(),
- // bytes to frame conversion: sample format is ENCODING_PCM_16BIT, 2 channels
+ // bytes to frame conversion:
// 1200 == minimum buffer size in frames on generation 1 hardware
- Math.max(1200, buffSizeInBytes / 4));
+ Math.max(1200, buffSizeInBytes /
+ (AudioFormat.getBytesPerSample(AudioFormat.ENCODING_PCM_16BIT) *
+ 2 /*channels*/)));
}
}
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index eb91668..d3b1520 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -28,9 +28,12 @@
import java.net.URL;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
+import java.net.NoRouteToHostException;
import java.util.HashMap;
import java.util.Map;
+import static android.media.MediaPlayer.MEDIA_ERROR_UNSUPPORTED;
+
/** @hide */
public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
private static final String TAG = "MediaHTTPConnection";
@@ -43,6 +46,12 @@
private long mTotalSize = -1;
private InputStream mInputStream = null;
+ private boolean mAllowCrossDomainRedirect = true;
+
+ // from com.squareup.okhttp.internal.http
+ private final static int HTTP_TEMP_REDIRECT = 307;
+ private final static int MAX_REDIRECTS = 20;
+
public MediaHTTPConnection() {
if (CookieHandler.getDefault() == null) {
CookieHandler.setDefault(new CookieManager());
@@ -59,6 +68,7 @@
try {
disconnect();
+ mAllowCrossDomainRedirect = true;
mURL = new URL(uri);
mHeaders = convertHeaderStringToMap(headers);
} catch (MalformedURLException e) {
@@ -68,6 +78,25 @@
return native_getIMemory();
}
+ private boolean parseBoolean(String val) {
+ try {
+ return Long.parseLong(val) != 0;
+ } catch (NumberFormatException e) {
+ return "true".equalsIgnoreCase(val) ||
+ "yes".equalsIgnoreCase(val);
+ }
+ }
+
+ /* returns true iff header is internal */
+ private boolean filterOutInternalHeaders(String key, String val) {
+ if ("android-allow-cross-domain-redirect".equalsIgnoreCase(key)) {
+ mAllowCrossDomainRedirect = parseBoolean(val);
+ } else {
+ return false;
+ }
+ return true;
+ }
+
private Map<String, String> convertHeaderStringToMap(String headers) {
HashMap<String, String> map = new HashMap<String, String>();
@@ -78,7 +107,9 @@
String key = pair.substring(0, colonPos);
String val = pair.substring(colonPos + 1);
- map.put(key, val);
+ if (!filterOutInternalHeaders(key, val)) {
+ map.put(key, val);
+ }
}
}
@@ -107,24 +138,75 @@
teardownConnection();
try {
- mConnection = (HttpURLConnection)mURL.openConnection();
+ int response;
+ int redirectCount = 0;
- if (mHeaders != null) {
- for (Map.Entry<String, String> entry : mHeaders.entrySet()) {
+ URL url = mURL;
+ while (true) {
+ mConnection = (HttpURLConnection)url.openConnection();
+ // handle redirects ourselves if we do not allow cross-domain redirect
+ mConnection.setInstanceFollowRedirects(mAllowCrossDomainRedirect);
+
+ if (mHeaders != null) {
+ for (Map.Entry<String, String> entry : mHeaders.entrySet()) {
+ mConnection.setRequestProperty(
+ entry.getKey(), entry.getValue());
+ }
+ }
+
+ if (offset > 0) {
mConnection.setRequestProperty(
- entry.getKey(), entry.getValue());
+ "Range", "bytes=" + offset + "-");
+ }
+
+ response = mConnection.getResponseCode();
+ if (response != HttpURLConnection.HTTP_MULT_CHOICE &&
+ response != HttpURLConnection.HTTP_MOVED_PERM &&
+ response != HttpURLConnection.HTTP_MOVED_TEMP &&
+ response != HttpURLConnection.HTTP_SEE_OTHER &&
+ response != HTTP_TEMP_REDIRECT) {
+ // not a redirect, or redirect handled by HttpURLConnection
+ break;
+ }
+
+ if (++redirectCount > MAX_REDIRECTS) {
+ throw new NoRouteToHostException("Too many redirects: " + redirectCount);
+ }
+
+ String method = mConnection.getRequestMethod();
+ if (response == HTTP_TEMP_REDIRECT &&
+ !method.equals("GET") && !method.equals("HEAD")) {
+ // "If the 307 status code is received in response to a
+ // request other than GET or HEAD, the user agent MUST NOT
+ // automatically redirect the request"
+ throw new NoRouteToHostException("Invalid redirect");
+ }
+ String location = mConnection.getHeaderField("Location");
+ if (location == null) {
+ throw new NoRouteToHostException("Invalid redirect");
+ }
+ url = new URL(mURL /* TRICKY: don't use url! */, location);
+ if (!url.getProtocol().equals("https") &&
+ !url.getProtocol().equals("http")) {
+ throw new NoRouteToHostException("Unsupported protocol redirect");
+ }
+ boolean sameHost = mURL.getHost().equals(url.getHost());
+ if (!sameHost) {
+ throw new NoRouteToHostException("Cross-domain redirects are disallowed");
+ }
+
+ if (response != HTTP_TEMP_REDIRECT) {
+ // update effective URL, unless it is a Temporary Redirect
+ mURL = url;
}
}
- if (offset > 0) {
- mConnection.setRequestProperty(
- "Range", "bytes=" + offset + "-");
+ if (mAllowCrossDomainRedirect) {
+ // remember the current, potentially redirected URL if redirects
+ // were handled by HttpURLConnection
+ mURL = mConnection.getURL();
}
- int response = mConnection.getResponseCode();
- // remember the current, possibly redirected URL
- mURL = mConnection.getURL();
-
if (response == HttpURLConnection.HTTP_PARTIAL) {
// Partial content, we cannot just use getContentLength
// because what we want is not just the length of the range
@@ -207,6 +289,9 @@
}
return n;
+ } catch (NoRouteToHostException e) {
+ Log.w(TAG, "readAt " + offset + " / " + size + " => " + e);
+ return MEDIA_ERROR_UNSUPPORTED;
} catch (IOException e) {
if (VERBOSE) {
Log.d(TAG, "readAt " + offset + " / " + size + " => -1");
diff --git a/media/java/android/media/session/MediaMetadata.java b/media/java/android/media/session/MediaMetadata.java
index 56bdf68..8a8af45 100644
--- a/media/java/android/media/session/MediaMetadata.java
+++ b/media/java/android/media/session/MediaMetadata.java
@@ -295,6 +295,15 @@
}
/**
+ * Get the number of fields in this metadata.
+ *
+ * @return The number of fields in the metadata.
+ */
+ public int size() {
+ return mBundle.size();
+ }
+
+ /**
* Helper for getting the String key used by {@link MediaMetadata} from the
* integer key that {@link MediaMetadataEditor} uses.
*
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 26eb9c4..3254e5d 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -225,6 +225,20 @@
}
@Override
+ public String toString() {
+ StringBuilder bob = new StringBuilder("PlaybackState {");
+ bob.append("state=").append(mState);
+ bob.append(", position=").append(mPosition);
+ bob.append(", buffered position=").append(mBufferPosition);
+ bob.append(", rate=").append(mRate);
+ bob.append(", updated=").append(mUpdateTime);
+ bob.append(", actions=").append(mActions);
+ bob.append(", error=").append(mErrorMessage);
+ bob.append("}");
+ return bob.toString();
+ }
+
+ @Override
public int describeContents() {
return 0;
}
diff --git a/packages/Keyguard/res/layout/keyguard_bouncer.xml b/packages/Keyguard/res/layout/keyguard_bouncer.xml
index 8716ebc..975a139 100644
--- a/packages/Keyguard/res/layout/keyguard_bouncer.xml
+++ b/packages/Keyguard/res/layout/keyguard_bouncer.xml
@@ -19,7 +19,7 @@
android:layout_height="match_parent">
<View android:id="@+id/bouncer_background"
- android:background="#aa000000"
+ android:background="#cc000000"
android:clickable="true"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
diff --git a/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml b/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
index 0e2b33a..e167817 100644
--- a/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
@@ -92,7 +92,7 @@
>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key1"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -101,7 +101,7 @@
/>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key2"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -110,7 +110,7 @@
/>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key3"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -126,7 +126,7 @@
>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key4"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -135,7 +135,7 @@
/>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key5"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -144,7 +144,7 @@
/>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key6"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -160,7 +160,7 @@
>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key7"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -169,7 +169,7 @@
/>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key8"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -178,7 +178,7 @@
/>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key9"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -199,7 +199,7 @@
/>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key0"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -208,7 +208,7 @@
/>
<ImageButton
android:id="@+id/key_enter"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
diff --git a/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml b/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
index 88049a7..ac798ca 100644
--- a/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
@@ -93,7 +93,7 @@
>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key1"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -102,7 +102,7 @@
/>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key2"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -111,7 +111,7 @@
/>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key3"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -127,7 +127,7 @@
>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key4"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -136,7 +136,7 @@
/>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key5"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -145,7 +145,7 @@
/>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key6"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -161,7 +161,7 @@
>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key7"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -170,7 +170,7 @@
/>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key8"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -179,7 +179,7 @@
/>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key9"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -200,7 +200,7 @@
/>
<view class="com.android.keyguard.NumPadKey"
android:id="@+id/key0"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -209,7 +209,7 @@
/>
<ImageButton
android:id="@+id/key_enter"
- style="@style/Widget.Button.NumPadKey"
+ style="@style/Widget.Button.NumPadKey.Sim"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1"
diff --git a/packages/Keyguard/res/values/styles.xml b/packages/Keyguard/res/values/styles.xml
index b54ac50..5ab00d2 100644
--- a/packages/Keyguard/res/values/styles.xml
+++ b/packages/Keyguard/res/values/styles.xml
@@ -33,6 +33,10 @@
<item name="android:paddingLeft">20dp</item>
<item name="android:paddingRight">6dp</item>
</style>
+ <style name="Widget.Button.NumPadKey.Sim" >
+ <item name="android:paddingTop">3dp</item>
+ <item name="android:paddingBottom">4dp</item>
+ </style>
<style name="TextAppearance.NumPadKey"
parent="@android:style/TextAppearance">
<item name="android:textSize">34dp</item>
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 327df8d..6b62c25 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -98,6 +98,9 @@
<uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
<uses-permission android:name="android.permission.TRUST_LISTENER" />
+ <!-- Recents -->
+ <uses-permission android:name="android.permission.BIND_APPWIDGET" />
+
<!-- Wifi Display -->
<uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
@@ -138,7 +141,7 @@
android:exported="true" />
<receiver android:name=".BootReceiver" androidprv:primaryUserOnly="true">
- <intent-filter>
+ <intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_camera_alt_24dp.png b/packages/SystemUI/res/drawable-hdpi/ic_camera_alt_24dp.png
new file mode 100644
index 0000000..253c73792
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_camera_alt_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_phone_24dp.png b/packages/SystemUI/res/drawable-hdpi/ic_phone_24dp.png
new file mode 100644
index 0000000..a6a6448
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_phone_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_camera.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_camera.png
deleted file mode 100644
index c6f03c4..0000000
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_camera.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_camera_alt_24dp.png b/packages/SystemUI/res/drawable-mdpi/ic_camera_alt_24dp.png
new file mode 100644
index 0000000..ee1187b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_camera_alt_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_phone_24dp.png b/packages/SystemUI/res/drawable-mdpi/ic_phone_24dp.png
new file mode 100644
index 0000000..2286bb4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_phone_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_camera.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_camera.png
deleted file mode 100644
index 1c2d7aa..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_camera.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_camera_alt_24dp.png b/packages/SystemUI/res/drawable-xhdpi/ic_camera_alt_24dp.png
new file mode 100644
index 0000000..268eba0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_camera_alt_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_phone_24dp.png b/packages/SystemUI/res/drawable-xhdpi/ic_phone_24dp.png
new file mode 100644
index 0000000..cd9ff60
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_phone_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_camera.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_camera.png
deleted file mode 100644
index fbd4d6b..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_camera.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_camera_alt_24dp.png b/packages/SystemUI/res/drawable-xxhdpi/ic_camera_alt_24dp.png
new file mode 100644
index 0000000..9175118
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_camera_alt_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_phone_24dp.png b/packages/SystemUI/res/drawable-xxhdpi/ic_phone_24dp.png
new file mode 100644
index 0000000..3c546e5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_phone_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_camera.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_camera.png
deleted file mode 100644
index 86df881..0000000
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_camera.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_camera_alt_24dp.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_camera_alt_24dp.png
new file mode 100644
index 0000000..20e26b8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_camera_alt_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_phone_24dp.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_phone_24dp.png
new file mode 100644
index 0000000..4f7da0a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_phone_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 809adcd..ec5acba 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -22,15 +22,29 @@
android:layout_height="match_parent"
android:layout_width="match_parent"
>
- <com.android.systemui.statusbar.policy.KeyButtonView
+ <com.android.systemui.statusbar.phone.SwipeAffordanceView
android:id="@+id/camera_button"
- android:layout_height="80dp"
- android:layout_width="80dp"
- android:layout_gravity="bottom|right"
- android:src="@drawable/ic_sysbar_camera"
+ android:layout_height="64dp"
+ android:layout_width="64dp"
+ android:layout_gravity="bottom|end"
+ android:tint="#ffffffff"
+ android:src="@drawable/ic_camera_alt_24dp"
android:scaleType="center"
android:contentDescription="@string/accessibility_camera_button"
- systemui:glowBackground="@drawable/ic_sysbar_highlight_land" />
+ systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
+ systemui:swipeDirection="start"/>
+
+ <com.android.systemui.statusbar.phone.SwipeAffordanceView
+ android:id="@+id/phone_button"
+ android:layout_height="64dp"
+ android:layout_width="64dp"
+ android:layout_gravity="bottom|start"
+ android:tint="#ffffffff"
+ android:src="@drawable/ic_phone_24dp"
+ android:scaleType="center"
+ android:contentDescription="@string/accessibility_phone_button"
+ systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
+ systemui:swipeDirection="end"/>
<com.android.systemui.statusbar.phone.KeyguardIndicationTextView
android:id="@+id/keyguard_indication_text"
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index ddc0dbf..f7df18eb 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -58,7 +58,7 @@
android:textSize="22sp"
android:textColor="#ffffffff"
android:text="@string/recents_empty_message"
- android:fontFamily="sans-serif-thin"
+ android:fontFamily="sans-serif-light"
android:singleLine="true"
android:maxLines="2"
android:ellipsize="marquee"
diff --git a/packages/SystemUI/res/values-sw720dp/config.xml b/packages/SystemUI/res/values-sw720dp/config.xml
index bf01a8d..7cf711a 100644
--- a/packages/SystemUI/res/values-sw720dp/config.xml
+++ b/packages/SystemUI/res/values-sw720dp/config.xml
@@ -32,5 +32,8 @@
<!-- Min alpha % that recent items will fade to while being dismissed -->
<integer name="config_recent_item_min_alpha">0</integer>
+
+ <!-- Transposes the search bar layout in landscape -->
+ <bool name="recents_transpose_search_layout_with_orientation">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 734abdc..f5674d2 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -45,6 +45,12 @@
<declare-styleable name="BatteryMeterView">
<attr name="frameColor" format="color" />
</declare-styleable>
+ <declare-styleable name="SwipeAffordanceView">
+ <attr name="swipeDirection" format="enum">
+ <enum name="start" value="0" />
+ <enum name="end" value="1" />
+ </attr>
+ </declare-styleable>
<attr name="orientation">
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 722ca15..c3ccb59 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -115,12 +115,16 @@
<integer name="recents_filter_animate_current_views_min_duration">175</integer>
<!-- The min animation duration for animating views that are newly visible. -->
<integer name="recents_filter_animate_new_views_min_duration">125</integer>
- <!-- The min animation duration for animating views that are newly visible. -->
+ <!-- The min animation duration for animating the task bar in. -->
<integer name="recents_animate_task_bar_enter_duration">200</integer>
+ <!-- The min animation duration for animating the task bar out. -->
+ <integer name="recents_animate_task_bar_exit_duration">150</integer>
<!-- The animation duration for animating in the info pane. -->
<integer name="recents_animate_task_view_info_pane_duration">150</integer>
<!-- The minimum alpha for the dim applied to cards that go deeper into the stack. -->
<integer name="recents_max_task_stack_view_dim">96</integer>
+ <!-- Transposes the search bar layout in landscape -->
+ <bool name="recents_transpose_search_layout_with_orientation">true</bool>
<!-- Whether to enable KeyguardService or not -->
<bool name="config_enableKeyguardService">true</bool>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 2f2914c..d763bd6 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -227,14 +227,17 @@
<!-- The radius of the rounded corners on a task view. -->
<dimen name="recents_task_view_rounded_corners_radius">2dp</dimen>
+ <!-- The min translation in the Z index for the last task. -->
+ <dimen name="recents_task_view_z_min">3dp</dimen>
+
+ <!-- The translation in the Z index for each task above the last task. -->
+ <dimen name="recents_task_view_z_increment">5dp</dimen>
+
<!-- The amount of space a user has to scroll to dismiss any info panes. -->
<dimen name="recents_task_stack_scroll_dismiss_info_pane_distance">50dp</dimen>
<!-- The height of the search bar space. -->
- <dimen name="recents_search_bar_space_height">40dp</dimen>
-
- <!-- The search bar edge margins. -->
- <dimen name="recents_search_bar_space_edge_margins">12dp</dimen>
+ <dimen name="recents_search_bar_space_height">64dp</dimen>
<!-- Used to calculate the translation animation duration, the expected amount of movement
in dps over one second of time. -->
@@ -261,8 +264,8 @@
<!-- Width of the zen mode interstitial dialog. -->
<dimen name="zen_mode_dialog_width">320dp</dimen>
- <!-- Camera affordance drag distance -->
- <dimen name="camera_drag_distance">100dp</dimen>
+ <!-- Lockscreen affordance drag distance for camera and phone. -->
+ <dimen name="affordance_drag_distance">100dp</dimen>
<dimen name="quick_settings_tmp_scrim_stroke_width">8dp</dimen>
<dimen name="quick_settings_tmp_scrim_text_size">30dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index b4a13d4..3f0a60f 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -196,6 +196,8 @@
<string name="accessibility_search_light">Search</string>
<!-- Content description of the camera button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_camera_button">Camera</string>
+ <!-- Content description of the phone button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_phone_button">Phone</string>
<!-- Content description of the switch input method button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_ime_switch_button">Switch input method button.</string>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 103991a..217074f 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -65,6 +65,8 @@
// the theme set there.
setTheme(R.style.systemui_theme);
+ IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -80,7 +82,7 @@
}
}
}
- }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+ }, filter);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index f2e322d..396cb14 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -64,6 +64,17 @@
mSingleCountFirstTaskRect.offset(0, (int) statusBarHeight);
mMultipleCountFirstTaskRect = replyData.getParcelable(KEY_MULTIPLE_TASK_STACK_RECT);
mMultipleCountFirstTaskRect.offset(0, (int) statusBarHeight);
+ Console.log(Constants.DebugFlags.App.RecentsComponent,
+ "[RecentsComponent|RecentsMessageHandler|handleMessage]",
+ "singleTaskRect: " + mSingleCountFirstTaskRect +
+ " multipleTaskRect: " + mMultipleCountFirstTaskRect);
+
+ // If we had the update the animation rects as a result of onServiceConnected, then
+ // we check for whether we need to toggle the recents here.
+ if (mToggleRecentsUponServiceBound) {
+ startAlternateRecentsActivity();
+ mToggleRecentsUponServiceBound = false;
+ }
}
}
}
@@ -78,11 +89,16 @@
mService = new Messenger(service);
mServiceIsBound = true;
- // Toggle recents if this service connection was triggered by hitting the recents button
- if (mToggleRecentsUponServiceBound) {
- startAlternateRecentsActivity();
+ if (hasValidTaskRects()) {
+ // Toggle recents if this new service connection was triggered by hitting recents
+ if (mToggleRecentsUponServiceBound) {
+ startAlternateRecentsActivity();
+ mToggleRecentsUponServiceBound = false;
+ }
+ } else {
+ // Otherwise, update the animation rects before starting the recents if requested
+ updateAnimationRects();
}
- mToggleRecentsUponServiceBound = false;
}
@Override
@@ -191,6 +207,26 @@
}
public void onConfigurationChanged(Configuration newConfig) {
+ updateAnimationRects();
+ }
+
+ /** Binds to the recents implementation */
+ private void bindToRecentsService(boolean toggleRecentsUponConnection) {
+ mToggleRecentsUponServiceBound = toggleRecentsUponConnection;
+ Intent intent = new Intent();
+ intent.setClassName(sRecentsPackage, sRecentsService);
+ mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+ }
+
+ /** Returns whether we have valid task rects to animate to. */
+ boolean hasValidTaskRects() {
+ return mSingleCountFirstTaskRect != null && mSingleCountFirstTaskRect.width() > 0 &&
+ mSingleCountFirstTaskRect.height() > 0 && mMultipleCountFirstTaskRect != null &&
+ mMultipleCountFirstTaskRect.width() > 0 && mMultipleCountFirstTaskRect.height() > 0;
+ }
+
+ /** Updates each of the task animation rects. */
+ void updateAnimationRects() {
if (mServiceIsBound) {
Resources res = mContext.getResources();
int statusBarHeight = res.getDimensionPixelSize(
@@ -216,14 +252,6 @@
}
}
- /** Binds to the recents implementation */
- private void bindToRecentsService(boolean toggleRecentsUponConnection) {
- mToggleRecentsUponServiceBound = toggleRecentsUponConnection;
- Intent intent = new Intent();
- intent.setClassName(sRecentsPackage, sRecentsService);
- mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
- }
-
/** Loads the first task thumbnail */
Bitmap loadFirstTaskThumbnail() {
SystemServicesProxy ssp = mSystemServicesProxy;
@@ -300,6 +328,49 @@
return SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
}
+ /** Creates the activity options for a thumbnail transition. */
+ ActivityOptions getThumbnailTransitionActivityOptions(Rect taskRect) {
+ // Loading from thumbnail
+ Bitmap thumbnail;
+ Bitmap firstThumbnail = loadFirstTaskThumbnail();
+ if (firstThumbnail != null) {
+ // Create the thumbnail
+ thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(),
+ Bitmap.Config.ARGB_8888);
+ int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight());
+ Canvas c = new Canvas(thumbnail);
+ c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size),
+ new Rect(0, 0, taskRect.width(), taskRect.height()), null);
+ c.setBitmap(null);
+ // Recycle the old thumbnail
+ firstThumbnail.recycle();
+ } else {
+ // Load the thumbnail from the screenshot if can't get one from the system
+ WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ Display display = wm.getDefaultDisplay();
+ Bitmap screenshot = takeScreenshot(display);
+ if (screenshot != null) {
+ Resources res = mContext.getResources();
+ int size = Math.min(screenshot.getWidth(), screenshot.getHeight());
+ int statusBarHeight = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+ thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(),
+ Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(thumbnail);
+ c.drawBitmap(screenshot, new Rect(0, statusBarHeight, size, statusBarHeight +
+ size), new Rect(0, 0, taskRect.width(), taskRect.height()), null);
+ c.setBitmap(null);
+ // Recycle the temporary screenshot
+ screenshot.recycle();
+ } else {
+ return null;
+ }
+ }
+
+ return ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView, thumbnail,
+ taskRect.left, taskRect.top, null);
+ }
+
/** Starts the recents activity */
void startAlternateRecentsActivity() {
// If the user has toggled it too quickly, then just eat up the event here (it's better than
@@ -351,47 +422,28 @@
// number of items in the list.
List<ActivityManager.RecentTaskInfo> recentTasks =
ssp.getRecentTasks(4, UserHandle.CURRENT.getIdentifier());
- boolean hasMultipleTasks = hasMultipleRecentsTask(recentTasks);
+ Rect taskRect = hasMultipleRecentsTask(recentTasks) ? mMultipleCountFirstTaskRect :
+ mSingleCountFirstTaskRect;
boolean isTaskExcludedFromRecents = isTopTaskExcludeFromRecents(recentTasks);
- Rect taskRect = hasMultipleTasks ? mMultipleCountFirstTaskRect : mSingleCountFirstTaskRect;
- if (!isTopTaskHome && !isTaskExcludedFromRecents &&
- (taskRect != null) && (taskRect.width() > 0) && (taskRect.height() > 0)) {
- // Loading from thumbnail
- Bitmap thumbnail;
- Bitmap firstThumbnail = loadFirstTaskThumbnail();
- if (firstThumbnail != null) {// Create the thumbnail
- thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(),
- Bitmap.Config.ARGB_8888);
- int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight());
- Canvas c = new Canvas(thumbnail);
- c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size),
- new Rect(0, 0, taskRect.width(), taskRect.height()), null);
- c.setBitmap(null);
- // Recycle the old thumbnail
- firstThumbnail.recycle();
- } else {
- // Load the thumbnail from the screenshot if can't get one from the system
- WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
- Display display = wm.getDefaultDisplay();
- Bitmap screenshot = takeScreenshot(display);
- Resources res = mContext.getResources();
- int size = Math.min(screenshot.getWidth(), screenshot.getHeight());
- int statusBarHeight = res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
- thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(),
- Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(thumbnail);
- c.drawBitmap(screenshot, new Rect(0, statusBarHeight, size, statusBarHeight + size),
- new Rect(0, 0, taskRect.width(), taskRect.height()), null);
- c.setBitmap(null);
- // Recycle the temporary screenshot
- screenshot.recycle();
- }
+ boolean useThumbnailTransition = !isTopTaskHome && !isTaskExcludedFromRecents &&
+ hasValidTaskRects();
- ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView,
- thumbnail, taskRect.left, taskRect.top, null);
- startAlternateRecentsActivity(opts, true);
- } else {
+ if (useThumbnailTransition) {
+ // Try starting with a thumbnail transition
+ ActivityOptions opts = getThumbnailTransitionActivityOptions(taskRect);
+ if (opts != null) {
+ startAlternateRecentsActivity(opts, true);
+ } else {
+ // Fall through below to the non-thumbnail transition
+ useThumbnailTransition = false;
+ }
+ }
+
+ // If there is no thumbnail transition, then just use a generic transition
+ // XXX: This should be different between home and from a recents-excluded app, perhaps the
+ // recents-excluded app should still show up in recents, when the app is in the
+ // foreground
+ if (!useThumbnailTransition) {
ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_launcher_enter,
R.anim.recents_from_launcher_exit);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Console.java b/packages/SystemUI/src/com/android/systemui/recents/Console.java
index 4b75c99..c8d97cc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Console.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Console.java
@@ -37,7 +37,7 @@
public static final String AnsiRed = "\u001B[31m"; // SystemUIHandshake
public static final String AnsiGreen = "\u001B[32m"; // MeasureAndLayout
public static final String AnsiYellow = "\u001B[33m"; // SynchronizeViewsWithModel
- public static final String AnsiBlue = "\u001B[34m"; // TouchEvents
+ public static final String AnsiBlue = "\u001B[34m"; // TouchEvents, Search
public static final String AnsiPurple = "\u001B[35m"; // Draw
public static final String AnsiCyan = "\u001B[36m"; // ClickEvents
public static final String AnsiWhite = "\u001B[37m";
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index a996c1a..90ea873 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -28,8 +28,9 @@
public static class App {
public static final boolean EnableTaskFiltering = false;
public static final boolean EnableTaskStackClipping = false;
+ public static final boolean EnableTaskBarThemeColors = true;
public static final boolean EnableInfoPane = true;
- public static final boolean EnableSearchButton = false;
+ public static final boolean EnableSearchButton = true;
// This disables the bitmap and icon caches
public static final boolean DisableBackgroundCache = false;
@@ -51,6 +52,7 @@
public static final boolean SystemUIHandshake = false;
public static final boolean TimeSystemCalls = false;
public static final boolean Memory = false;
+ public static final boolean Search = false;
}
public static class UI {
@@ -71,6 +73,10 @@
}
public static class Values {
+ public static class App {
+ public static int AppWidgetHostId = 1024;
+ public static String Key_SearchAppWidgetId = "searchAppWidgetId";
+ }
public static class Window {
// The dark background dim is set behind the empty recents view
public static final float DarkBackgroundDim = 0.5f;
@@ -85,11 +91,8 @@
public static final int TaskStackOverscrollRange = 150;
public static final int FilterStartDelay = 25;
- // The amount to inverse scale the movement if we are overscrolling
- public static final float TouchOverscrollScaleFactor = 3f;
-
// The padding will be applied to the smallest dimension, and then applied to all sides
- public static final float StackPaddingPct = 0.15f;
+ public static final float StackPaddingPct = 0.1f;
// The overlap height relative to the task height
public static final float StackOverlapPct = 0.65f;
// The height of the peek space relative to the stack height
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 71c45f2..110130b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -17,11 +17,17 @@
package com.android.systemui.recents;
import android.app.Activity;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetHostView;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
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.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
@@ -33,13 +39,37 @@
import java.util.ArrayList;
+/** Our special app widget host */
+class RecentsAppWidgetHost extends AppWidgetHost {
+ /* Callbacks to notify when an app package changes */
+ interface RecentsAppWidgetHostCallbacks {
+ public void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo);
+ }
+
+ RecentsAppWidgetHostCallbacks mCb;
+
+ public RecentsAppWidgetHost(Context context, int hostId, RecentsAppWidgetHostCallbacks cb) {
+ super(context, hostId);
+ mCb = cb;
+ }
+
+ @Override
+ protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidget) {
+ mCb.onProviderChanged(appWidgetId, appWidget);
+ }
+}
/* Activity */
-public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks {
+public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks,
+ RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks{
FrameLayout mContainerView;
RecentsView mRecentsView;
View mEmptyView;
+ AppWidgetHost mAppWidgetHost;
+ AppWidgetProviderInfo mSearchAppWidgetInfo;
+ AppWidgetHostView mSearchAppWidgetHostView;
+
boolean mVisible;
boolean mTaskLaunched;
@@ -102,6 +132,75 @@
}
}
+ /** Attempts to allocate and bind the search bar app widget */
+ void bindSearchBarAppWidget() {
+ if (Constants.DebugFlags.App.EnableSearchButton) {
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
+
+ // Reset the host view and widget info
+ mSearchAppWidgetHostView = null;
+ mSearchAppWidgetInfo = null;
+
+ // Try and load the app widget id from the settings
+ int appWidgetId = config.searchBarAppWidgetId;
+ if (appWidgetId >= 0) {
+ mSearchAppWidgetInfo = ssp.getAppWidgetInfo(appWidgetId);
+ if (mSearchAppWidgetInfo == null) {
+ // If there is no actual widget associated with that id, then delete it and
+ // prepare to bind another app widget in its place
+ ssp.unbindSearchAppWidget(mAppWidgetHost, appWidgetId);
+ appWidgetId = -1;
+ }
+ Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+ "[RecentsActivity|onCreate|settings|appWidgetId]",
+ "Id: " + appWidgetId,
+ Console.AnsiBlue);
+ }
+
+ // If there is no id, then bind a new search app widget
+ if (appWidgetId < 0) {
+ Pair<Integer, AppWidgetProviderInfo> widgetInfo =
+ ssp.bindSearchAppWidget(mAppWidgetHost);
+ if (widgetInfo != null) {
+ Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+ "[RecentsActivity|onCreate|searchWidget]",
+ "Id: " + widgetInfo.first + " Info: " + widgetInfo.second,
+ Console.AnsiBlue);
+
+ // Save the app widget id into the settings
+ config.updateSearchBarAppWidgetId(this, widgetInfo.first);
+ mSearchAppWidgetInfo = widgetInfo.second;
+ }
+ }
+ }
+ }
+
+ /** Creates the search bar app widget view */
+ void addSearchBarAppWidgetView() {
+ if (Constants.DebugFlags.App.EnableSearchButton) {
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ int appWidgetId = config.searchBarAppWidgetId;
+ if (appWidgetId >= 0) {
+ Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+ "[RecentsActivity|onCreate|addSearchAppWidgetView]",
+ "Id: " + appWidgetId,
+ Console.AnsiBlue);
+ mSearchAppWidgetHostView = mAppWidgetHost.createView(this, appWidgetId,
+ mSearchAppWidgetInfo);
+ Bundle opts = new Bundle();
+ opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
+ AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+ mSearchAppWidgetHostView.updateAppWidgetOptions(opts);
+ // Set the padding to 0 for this search widget
+ mSearchAppWidgetHostView.setPadding(0, 0, 0, 0);
+ mRecentsView.setSearchBar(mSearchAppWidgetHostView);
+ } else {
+ mRecentsView.setSearchBar(null);
+ }
+ }
+ }
+
/** Dismisses recents if we are already visible and the intent is to toggle the recents view */
boolean dismissRecentsIfVisible() {
if (mVisible) {
@@ -127,6 +226,9 @@
RecentsTaskLoader.initialize(this);
RecentsConfiguration.reinitialize(this);
+ // Initialize the widget host (the host id is static and does not change)
+ mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId, this);
+
// Create the view hierarchy
mRecentsView = new RecentsView(this);
mRecentsView.setCallbacks(this);
@@ -145,6 +247,11 @@
// Update the recent tasks
updateRecentsTasks(getIntent());
+
+ // Bind the search app widget when we first start up
+ bindSearchBarAppWidget();
+ // Add the search bar layout
+ addSearchBarAppWidgetView();
}
@Override
@@ -165,6 +272,9 @@
// Update the recent tasks
updateRecentsTasks(intent);
+
+ // Don't attempt to rebind the search bar widget, but just add the search bar layout
+ addSearchBarAppWidgetView();
}
@Override
@@ -172,6 +282,7 @@
Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsActivity|onStart]", "",
Console.AnsiRed);
super.onStart();
+ mAppWidgetHost.startListening();
mVisible = true;
}
@@ -225,6 +336,7 @@
Console.AnsiRed);
super.onStop();
+ mAppWidgetHost.stopListening();
mVisible = false;
mTaskLaunched = false;
}
@@ -265,4 +377,18 @@
public void onTaskLaunching() {
mTaskLaunched = true;
}
+
+ @Override
+ public void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo) {
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
+ if (appWidgetId > -1 && appWidgetId == config.searchBarAppWidgetId) {
+ // The search provider may have changed, so just delete the old widget and bind it again
+ ssp.unbindSearchAppWidget(mAppWidgetHost, appWidgetId);
+ config.updateSearchBarAppWidgetId(this, -1);
+ // Load the widget again
+ bindSearchBarAppWidget();
+ addSearchBarAppWidgetView();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index d54df13..d1a3954 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -17,6 +17,7 @@
package com.android.systemui.recents;
import android.content.Context;
+import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
@@ -35,17 +36,28 @@
public Rect systemInsets = new Rect();
public Rect displayRect = new Rect();
+ boolean isLandscape;
+ boolean transposeSearchLayoutWithOrientation;
+ int searchBarAppWidgetId = -1;
+
public float animationPxMovementPerSecond;
public int filteringCurrentViewsMinAnimDuration;
public int filteringNewViewsMinAnimDuration;
public int taskBarEnterAnimDuration;
+ public int taskBarExitAnimDuration;
public int taskStackScrollDismissInfoPaneDistance;
public int taskStackMaxDim;
public int taskViewInfoPaneAnimDuration;
+ public int taskViewTranslationZMinPx;
+ public int taskViewTranslationZIncrementPx;
public int taskViewRoundedCornerRadiusPx;
public int searchBarSpaceHeightPx;
- public int searchBarSpaceEdgeMarginsPx;
+
+ public int taskBarViewDefaultBackgroundColor;
+ public int taskBarViewDefaultTextColor;
+ public int taskBarViewLightTextColor;
+ public int taskBarViewDarkTextColor;
public boolean launchedWithThumbnailAnimation;
@@ -72,8 +84,10 @@
DisplayMetrics dm = res.getDisplayMetrics();
mDisplayMetrics = dm;
- boolean isLandscape = res.getConfiguration().orientation ==
+ isLandscape = res.getConfiguration().orientation ==
Configuration.ORIENTATION_LANDSCAPE;
+ transposeSearchLayoutWithOrientation =
+ res.getBoolean(R.bool.recents_transpose_search_layout_with_orientation);
Console.log(Constants.DebugFlags.UI.MeasureAndLayout,
"[RecentsConfiguration|orientation]", isLandscape ? "Landscape" : "Portrait",
Console.AnsiGreen);
@@ -87,6 +101,8 @@
res.getInteger(R.integer.recents_filter_animate_new_views_min_duration);
taskBarEnterAnimDuration =
res.getInteger(R.integer.recents_animate_task_bar_enter_duration);
+ taskBarExitAnimDuration =
+ res.getInteger(R.integer.recents_animate_task_bar_exit_duration);
taskStackScrollDismissInfoPaneDistance = res.getDimensionPixelSize(
R.dimen.recents_task_stack_scroll_dismiss_info_pane_distance);
taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim);
@@ -94,9 +110,24 @@
res.getInteger(R.integer.recents_animate_task_view_info_pane_duration);
taskViewRoundedCornerRadiusPx =
res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
+ taskViewTranslationZMinPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min);
+ taskViewTranslationZIncrementPx =
+ res.getDimensionPixelSize(R.dimen.recents_task_view_z_increment);
searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height);
- searchBarSpaceEdgeMarginsPx =
- res.getDimensionPixelSize(R.dimen.recents_search_bar_space_edge_margins);
+
+
+ taskBarViewDefaultBackgroundColor =
+ res.getColor(R.color.recents_task_bar_default_background_color);
+ taskBarViewDefaultTextColor =
+ res.getColor(R.color.recents_task_bar_default_text_color);
+ taskBarViewLightTextColor =
+ res.getColor(R.color.recents_task_bar_light_text_color);
+ taskBarViewDarkTextColor =
+ res.getColor(R.color.recents_task_bar_dark_text_color);
+
+ // Update the search widget id
+ SharedPreferences settings = context.getSharedPreferences(context.getPackageName(), 0);
+ searchBarAppWidgetId = settings.getInt(Constants.Values.App.Key_SearchAppWidgetId, -1);
}
/** Updates the system insets */
@@ -104,24 +135,57 @@
systemInsets.set(insets);
}
- /** Returns the search bar bounds in the specified orientation */
- public void getSearchBarBounds(int width, int height,
- Rect searchBarSpaceBounds, Rect searchBarBounds) {
+ /** Updates the search bar app widget */
+ public void updateSearchBarAppWidgetId(Context context, int appWidgetId) {
+ searchBarAppWidgetId = appWidgetId;
+ SharedPreferences settings = context.getSharedPreferences(context.getPackageName(), 0);
+ settings.edit().putInt(Constants.Values.App.Key_SearchAppWidgetId,
+ appWidgetId).apply();
+ }
+
+ /** Returns whether the search bar app widget exists */
+ public boolean hasSearchBarAppWidget() {
+ return searchBarAppWidgetId >= 0;
+ }
+
+ /**
+ * Returns the task stack bounds in the current orientation. These bounds do not account for
+ * the system insets.
+ */
+ public void getTaskStackBounds(int width, int height, Rect taskStackBounds) {
+ if (hasSearchBarAppWidget()) {
+ Rect searchBarBounds = new Rect();
+ getSearchBarBounds(width, height, searchBarBounds);
+ if (isLandscape && transposeSearchLayoutWithOrientation) {
+ // In landscape, the search bar appears on the left, so shift the task rect right
+ taskStackBounds.set(searchBarBounds.width(), 0, width, height);
+ } else {
+ // In portrait, the search bar appears on the top, so shift the task rect below
+ taskStackBounds.set(0, searchBarBounds.height(), width, height);
+ }
+ } else {
+ taskStackBounds.set(0, 0, width, height);
+ }
+ }
+
+ /**
+ * Returns the search bar bounds in the current orientation. These bounds do not account for
+ * the system insets.
+ */
+ public void getSearchBarBounds(int width, int height, Rect searchBarSpaceBounds) {
// Return empty rects if search is not enabled
if (!Constants.DebugFlags.App.EnableSearchButton) {
searchBarSpaceBounds.set(0, 0, 0, 0);
- searchBarBounds.set(0, 0, 0, 0);
return;
}
- // Calculate the search bar bounds, and account for the system insets
- int edgeMarginPx = searchBarSpaceEdgeMarginsPx;
- int availableWidth = width - systemInsets.left - systemInsets.right;
- searchBarSpaceBounds.set(0, 0, availableWidth, 2 * edgeMarginPx + searchBarSpaceHeightPx);
-
- // Inset from the search bar space to get the search bar bounds
- searchBarBounds.set(searchBarSpaceBounds);
- searchBarBounds.inset(edgeMarginPx, edgeMarginPx);
+ if (isLandscape && transposeSearchLayoutWithOrientation) {
+ // In landscape, the search bar appears on the left
+ searchBarSpaceBounds.set(0, 0, searchBarSpaceHeightPx, height);
+ } else {
+ // In portrait, the search bar appears on the top
+ searchBarSpaceBounds.set(0, 0, width, searchBarSpaceHeightPx);
+ }
}
/** Converts from DPs to PXs */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 36b761e..0c6ed84 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -60,39 +60,41 @@
Rect windowRect = data.getParcelable(AlternateRecentsComponent.KEY_WINDOW_RECT);
Rect systemInsets = data.getParcelable(AlternateRecentsComponent.KEY_SYSTEM_INSETS);
+ // NOTE: None of the rects computed below need to be offset for the status bar,
+ // since that is done when we compute the animation itself in the Recents component
+
// Create a dummy task stack & compute the rect for the thumbnail to animate to
TaskStack stack = new TaskStack(context);
TaskStackView tsv = new TaskStackView(context, stack);
Bundle replyData = new Bundle();
TaskViewTransform transform;
- // Get the search bar bounds so that we can account for its height in the children
- Rect searchBarSpaceBounds = new Rect();
- Rect searchBarBounds = new Rect();
+ // Get the task stack and search bar bounds
+ Rect taskStackBounds = new Rect();
RecentsConfiguration config = RecentsConfiguration.getInstance();
- config.getSearchBarBounds(windowRect.width(), windowRect.height(),
- searchBarSpaceBounds, searchBarBounds);
+ config.getTaskStackBounds(windowRect.width(), windowRect.height(), taskStackBounds);
- // Calculate the target task rect for when there is one task
+ // Calculate the target task rect for when there is one task.
+
// NOTE: Since the nav bar height is already accounted for in the windowRect, don't
- // pass in a bottom inset
+ // pass in a left or bottom inset
stack.addTask(new Task());
- tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top -
- systemInsets.bottom - searchBarSpaceBounds.height(), 0);
+ tsv.computeRects(taskStackBounds.width(), taskStackBounds.height() -
+ systemInsets.top - systemInsets.bottom, 0, 0);
tsv.boundScroll();
transform = tsv.getStackTransform(0, tsv.getStackScroll());
- transform.rect.offset(0, searchBarSpaceBounds.height());
+ transform.rect.offset(taskStackBounds.left, taskStackBounds.top);
replyData.putParcelable(AlternateRecentsComponent.KEY_SINGLE_TASK_STACK_RECT,
new Rect(transform.rect));
- // Also calculate the target task rect when there are multiple tasks
+ // Also calculate the target task rect when there are multiple tasks.
stack.addTask(new Task());
- tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top -
- systemInsets.bottom - searchBarSpaceBounds.height(), 0);
+ tsv.computeRects(taskStackBounds.width(), taskStackBounds.height() -
+ systemInsets.top - systemInsets.bottom, 0, 0);
tsv.setStackScrollRaw(Integer.MAX_VALUE);
tsv.boundScroll();
transform = tsv.getStackTransform(1, tsv.getStackScroll());
- transform.rect.offset(0, searchBarSpaceBounds.height());
+ transform.rect.offset(taskStackBounds.left, taskStackBounds.top);
replyData.putParcelable(AlternateRecentsComponent.KEY_MULTIPLE_TASK_STACK_RECT,
new Rect(transform.rect));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index 52bba4a..4a19027 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -415,17 +415,23 @@
ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent(), t.userId);
if (info == null) continue;
- String activityLabel = (t.activityLabel == null ? ssp.getActivityLabel(info) :
- t.activityLabel.toString());
+ ActivityManager.RecentsActivityValues av = t.activityValues;
+ String activityLabel = null;
BitmapDrawable activityIcon = null;
- if (t.activityIcon != null) {
- activityIcon = new BitmapDrawable(res, t.activityIcon);
+ int activityColor = 0;
+ if (av != null) {
+ activityLabel = (av.label != null ? av.label.toString() :
+ ssp.getActivityLabel(info));
+ activityIcon = (av.icon != null) ? new BitmapDrawable(res, av.icon) : null;
+ activityColor = av.colorPrimary;
+ } else {
+ activityLabel = ssp.getActivityLabel(info);
}
boolean isForemostTask = (i == (taskCount - 1));
// Create a new task
Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, activityLabel,
- activityIcon, t.userId);
+ activityIcon, activityColor, t.userId);
// Preload the specified number of apps
if (i >= (taskCount - preloadCount)) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index 33ac0a8..c3b8a20 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -20,7 +20,9 @@
import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.SearchManager;
-import android.content.ActivityNotFoundException;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -35,8 +37,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
-import android.text.TextUtils;
-import android.util.Log;
+import android.util.Pair;
import java.util.ArrayList;
import java.util.List;
@@ -48,23 +49,32 @@
*/
public class SystemServicesProxy {
ActivityManager mAm;
+ AppWidgetManager mAwm;
PackageManager mPm;
IPackageManager mIpm;
UserManager mUm;
SearchManager mSm;
String mPackage;
+ ComponentName mAssistComponent;
Bitmap mDummyIcon;
/** Private constructor */
public SystemServicesProxy(Context context) {
mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ mAwm = AppWidgetManager.getInstance(context);
mPm = context.getPackageManager();
mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
mIpm = AppGlobals.getPackageManager();
mSm = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
mPackage = context.getPackageName();
+ // Resolve the assist intent
+ Intent assist = mSm.getAssistIntent(context, false);
+ if (assist != null) {
+ mAssistComponent = assist.getComponent();
+ }
+
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
// Create a dummy icon
mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
@@ -91,10 +101,13 @@
rti.id = rti.persistentId = i;
rti.baseIntent = new Intent();
rti.baseIntent.setComponent(cn);
- rti.description = rti.activityLabel = "" + i + " - " +
+ rti.activityValues = new ActivityManager.RecentsActivityValues();
+ rti.description = "" + i + " - " +
Long.toString(Math.abs(new Random().nextLong()), 36);
if (i % 2 == 0) {
- rti.activityIcon = Bitmap.createBitmap(mDummyIcon);
+ rti.activityValues.label = rti.description;
+ rti.activityValues.icon = Bitmap.createBitmap(mDummyIcon);
+ rti.activityValues.colorPrimary = new Random().nextInt();
}
tasks.add(rti);
}
@@ -103,7 +116,7 @@
return mAm.getRecentTasksForUser(numTasks,
ActivityManager.RECENT_IGNORE_UNAVAILABLE |
- ActivityManager.RECENT_INCLUDE_PROFILES, userId);
+ ActivityManager.RECENT_INCLUDE_PROFILES, userId);
}
/** Returns a list of the running tasks */
@@ -162,7 +175,7 @@
/**
* Returns the activity info for a given component name.
*
- * @param ComponentName The component name of the activity.
+ * @param cn The component name of the activity.
* @param userId The userId of the user that this is for.
*/
public ActivityInfo getActivityInfo(ComponentName cn, int userId) {
@@ -177,6 +190,23 @@
}
}
+ /**
+ * Returns the activity info for a given component name.
+ *
+ * @param cn The component name of the activity.
+ */
+ 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;
@@ -208,27 +238,54 @@
return icon;
}
+ /**
+ * Resolves and binds the search app widget that is to appear in the recents.
+ */
+ public Pair<Integer, AppWidgetProviderInfo> bindSearchAppWidget(AppWidgetHost host) {
+ if (mAwm == null) return null;
+ if (mAssistComponent == null) return null;
+
+ // Find the first Recents widget from the same package as the global assist activity
+ List<AppWidgetProviderInfo> widgets = mAwm.getInstalledProviders(
+ AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+ AppWidgetProviderInfo searchWidgetInfo = null;
+ for (AppWidgetProviderInfo info : widgets) {
+ if (info.provider.getPackageName().equals(mAssistComponent.getPackageName())) {
+ searchWidgetInfo = info;
+ break;
+ }
+ }
+
+ // Return early if there is no search widget
+ if (searchWidgetInfo == null) return null;
+
+ // Allocate a new widget id and try and bind the app widget (if that fails, then just skip)
+ int searchWidgetId = host.allocateAppWidgetId();
+ Bundle opts = new Bundle();
+ opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
+ AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+ if (!mAwm.bindAppWidgetIdIfAllowed(searchWidgetId, searchWidgetInfo.provider, opts)) {
+ return null;
+ }
+ return new Pair<Integer, AppWidgetProviderInfo>(searchWidgetId, searchWidgetInfo);
+ }
/**
- * Composes an intent to launch the global search activity.
+ * Returns the app widget info for the specified app widget id.
*/
- public Intent getGlobalSearchIntent(Rect sourceBounds) {
- if (mSm == null) return null;
+ public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
+ if (mAwm == null) return null;
- // Try and get the global search activity
- ComponentName globalSearchActivity = mSm.getGlobalSearchActivity();
- if (globalSearchActivity == null) return null;
+ return mAwm.getAppWidgetInfo(appWidgetId);
+ }
- // Bundle the source of the search
- Bundle appSearchData = new Bundle();
- appSearchData.putString("source", mPackage);
+ /**
+ * Destroys the specified app widget.
+ */
+ public void unbindSearchAppWidget(AppWidgetHost host, int appWidgetId) {
+ if (mAwm == null) return;
- // Compose the intent and Start the search activity
- Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.setComponent(globalSearchActivity);
- intent.putExtra(SearchManager.APP_DATA, appSearchData);
- intent.setSourceBounds(sourceBounds);
- return intent;
+ // Delete the app widget
+ host.deleteAppWidgetId(appWidgetId);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
index 4a1b3b2..b602f84 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
@@ -16,6 +16,7 @@
package com.android.systemui.recents;
+import android.graphics.Color;
import android.graphics.Rect;
/* Common code */
@@ -46,4 +47,19 @@
r.offset(cx, cy);
}
}
+
+ /** Calculates the luminance-preserved greyscale of a given color. */
+ private static int colorToGreyscale(int color) {
+ return Math.round(0.2126f * Color.red(color) + 0.7152f * Color.green(color) +
+ 0.0722f * Color.blue(color));
+ }
+
+ /** Returns the ideal text color to draw on top of a specified background color. */
+ public static int getIdealTextColorForBackgroundColor(int color) {
+ RecentsConfiguration configuration = RecentsConfiguration.getInstance();
+ int greyscale = colorToGreyscale(color);
+ return (greyscale < 128) ? configuration.taskBarViewLightTextColor :
+ configuration.taskBarViewDarkTextColor;
+
+ }
}
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 1566a49..47a506c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -72,6 +72,7 @@
public Drawable applicationIcon;
public Drawable activityIcon;
public String activityLabel;
+ public int colorPrimary;
public Bitmap thumbnail;
public boolean isActive;
public int userId;
@@ -83,10 +84,11 @@
}
public Task(int id, boolean isActive, Intent intent, String activityTitle,
- BitmapDrawable activityIcon, int userId) {
+ BitmapDrawable activityIcon, int colorPrimary, int userId) {
this.key = new TaskKey(id, intent, userId);
this.activityLabel = activityTitle;
this.activityIcon = activityIcon;
+ this.colorPrimary = colorPrimary;
this.isActive = isActive;
this.userId = userId;
}
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 a04cd3e..c2e8275 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -27,11 +27,9 @@
import android.net.Uri;
import android.os.UserHandle;
import android.provider.Settings;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
-import android.widget.TextView;
import com.android.systemui.recents.Console;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
@@ -39,7 +37,6 @@
import com.android.systemui.recents.model.SpaceNode;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.R;
import java.util.ArrayList;
@@ -57,6 +54,8 @@
// The space partitioning root of this container
SpaceNode mBSP;
+ // Whether there are any tasks
+ boolean mHasTasks;
// Search bar view
View mSearchBar;
// Recents view callbacks
@@ -80,22 +79,14 @@
mBSP = n;
// Create and add all the stacks for this partition of space.
- boolean hasTasks = false;
+ mHasTasks = false;
removeAllViews();
ArrayList<TaskStack> stacks = mBSP.getStacks();
for (TaskStack stack : stacks) {
TaskStackView stackView = new TaskStackView(getContext(), stack);
stackView.setCallbacks(this);
addView(stackView);
- hasTasks |= (stack.getTaskCount() > 0);
- }
-
- // Create the search bar (and hide it if we have no recent tasks)
- if (Constants.DebugFlags.App.EnableSearchButton) {
- createSearchBar();
- if (!hasTasks) {
- mSearchBar.setVisibility(View.GONE);
- }
+ mHasTasks |= (stack.getTaskCount() > 0);
}
}
@@ -130,19 +121,30 @@
return false;
}
- /** Creates and adds the search bar */
- void createSearchBar() {
- // Create a temporary search bar
- mSearchBar = mInflater.inflate(R.layout.recents_search_bar, this, false);
- mSearchBar.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- onSearchTriggered();
+ /** Adds the search bar */
+ public void setSearchBar(View searchBar) {
+ // Create the search bar (and hide it if we have no recent tasks)
+ if (Constants.DebugFlags.App.EnableSearchButton) {
+ // Remove the previous search bar if one exists
+ if (mSearchBar != null && indexOfChild(mSearchBar) > -1) {
+ removeView(mSearchBar);
}
- });
- addView(mSearchBar);
+ // Add the new search bar
+ if (searchBar != null) {
+ mSearchBar = searchBar;
+ mSearchBar.setVisibility(mHasTasks ? View.VISIBLE : View.GONE);
+ addView(mSearchBar);
+
+ Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsView|setSearchBar]",
+ "" + (mSearchBar.getVisibility() == View.VISIBLE),
+ Console.AnsiBlue);
+ }
+ }
}
+ /**
+ * This is called with the full size of the window since we are handling our own insets.
+ */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
@@ -155,22 +157,26 @@
Console.logTraceTime(Constants.DebugFlags.App.TimeRecentsStartup,
Constants.DebugFlags.App.TimeRecentsStartupKey, "RecentsView.onMeasure");
- // Get the search bar bounds so that we can account for its height in the children
- Rect searchBarSpaceBounds = new Rect();
- Rect searchBarBounds = new Rect();
+ // Get the search bar bounds and measure the search bar layout
RecentsConfiguration config = RecentsConfiguration.getInstance();
- config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
- searchBarSpaceBounds, searchBarBounds);
if (mSearchBar != null) {
- mSearchBar.measure(MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), widthMode),
- MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.height(), heightMode));
+ Rect searchBarSpaceBounds = new Rect();
+ config.getSearchBarBounds(width, height - config.systemInsets.top, searchBarSpaceBounds);
+ mSearchBar.measure(
+ MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.height(), MeasureSpec.EXACTLY));
}
- // We measure our stack views sans the status bar. It will handle the nav bar itself.
+ // We give the full width of the space, not including the right nav bar insets in landscape,
+ // to the stack view, since we want the tasks to render under the search bar in landscape.
+ // In addition, we give it the full height, not including the top inset or search bar space,
+ // since we want the tasks to render under the navigation buttons in portrait.
+ Rect taskStackBounds = new Rect();
+ config.getTaskStackBounds(width, height, taskStackBounds);
int childWidth = width - config.systemInsets.right;
- int childHeight = height - config.systemInsets.top - searchBarSpaceBounds.height();
+ int childHeight = taskStackBounds.height() - config.systemInsets.top;
- // Measure each child
+ // Measure each TaskStackView
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
@@ -183,6 +189,9 @@
setMeasuredDimension(width, height);
}
+ /**
+ * This is called with the full size of the window since we are handling our own insets.
+ */
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
Console.log(Constants.DebugFlags.UI.MeasureAndLayout, "[RecentsView|layout]",
@@ -190,21 +199,24 @@
Console.logTraceTime(Constants.DebugFlags.App.TimeRecentsStartup,
Constants.DebugFlags.App.TimeRecentsStartupKey, "RecentsView.onLayout");
- // Get the search bar bounds so that we can account for its height in the children
- Rect searchBarSpaceBounds = new Rect();
- Rect searchBarBounds = new Rect();
+ // Get the search bar bounds so that we lay it out
RecentsConfiguration config = RecentsConfiguration.getInstance();
- config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
- searchBarSpaceBounds, searchBarBounds);
if (mSearchBar != null) {
+ Rect searchBarSpaceBounds = new Rect();
+ config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(), searchBarSpaceBounds);
mSearchBar.layout(config.systemInsets.left + searchBarSpaceBounds.left,
config.systemInsets.top + searchBarSpaceBounds.top,
config.systemInsets.left + mSearchBar.getMeasuredWidth(),
config.systemInsets.top + mSearchBar.getMeasuredHeight());
}
- // We offset our stack views by the status bar height. It will handle the nav bar itself.
- top += config.systemInsets.top + searchBarSpaceBounds.height();
+ // We offset the stack view by the left inset (if any), but lay it out under the search bar.
+ // In addition, we offset our stack views by the top inset and search bar height, but not
+ // the bottom insets because we want it to render under the navigation buttons.
+ Rect taskStackBounds = new Rect();
+ config.getTaskStackBounds(getMeasuredWidth(), getMeasuredHeight(), taskStackBounds);
+ left += config.systemInsets.left;
+ top += config.systemInsets.top + taskStackBounds.top;
// Layout each child
// XXX: Based on the space node for that task view
@@ -212,9 +224,8 @@
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child instanceof TaskStackView && child.getVisibility() != GONE) {
- int width = child.getMeasuredWidth();
- int height = child.getMeasuredHeight();
- child.layout(left, top, left + width, top + height);
+ TaskStackView tsv = (TaskStackView) child;
+ child.layout(left, top, left + tsv.getMeasuredWidth(), top + tsv.getMeasuredHeight());
}
}
}
@@ -374,24 +385,4 @@
TaskStackBuilder.create(getContext())
.addNextIntentWithParentStack(intent).startActivities();
}
-
- public void onSearchTriggered() {
- // Get the search bar source bounds
- Rect searchBarSpaceBounds = new Rect();
- Rect searchBarBounds = new Rect();
- RecentsConfiguration config = RecentsConfiguration.getInstance();
- config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
- searchBarSpaceBounds, searchBarBounds);
-
- // Get the search intent and start it
- Intent searchIntent = RecentsTaskLoader.getInstance().getSystemServicesProxy()
- .getGlobalSearchIntent(searchBarBounds);
- if (searchIntent != null) {
- try {
- getContext().startActivity(searchIntent);
- } catch (ActivityNotFoundException anfe) {
- Console.logError(getContext(), "Could not start Search activity");
- }
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
index 124f11e..c6cb812 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -18,11 +18,13 @@
import android.content.Context;
import android.util.AttributeSet;
-import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.systemui.R;
+import com.android.systemui.recents.Constants;
+import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.Utilities;
import com.android.systemui.recents.model.Task;
@@ -58,6 +60,7 @@
/** Binds the bar view to the task */
void rebindToTask(Task t, boolean animate) {
+ RecentsConfiguration configuration = RecentsConfiguration.getInstance();
mTask = t;
// If an activity icon is defined, then we use that as the primary icon to show in the bar,
// otherwise, we fall back to the application icon
@@ -67,6 +70,15 @@
mApplicationIcon.setImageDrawable(t.applicationIcon);
}
mActivityDescription.setText(t.activityLabel);
+ // Try and apply the system ui tint
+ int tint = t.colorPrimary;
+ if (Constants.DebugFlags.App.EnableTaskBarThemeColors && tint != 0) {
+ setBackgroundColor(tint);
+ mActivityDescription.setTextColor(Utilities.getIdealTextColorForBackgroundColor(tint));
+ } else {
+ setBackgroundColor(configuration.taskBarViewDefaultBackgroundColor);
+ mActivityDescription.setTextColor(configuration.taskBarViewDefaultTextColor);
+ }
if (animate) {
// XXX: Investigate how expensive it will be to create a second bitmap and crossfade
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
index a81d01c..c6c29a6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
@@ -20,16 +20,21 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
+import android.content.res.ColorStateList;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
+import android.graphics.drawable.TouchFeedbackDrawable;
import android.util.AttributeSet;
import android.widget.Button;
import android.widget.FrameLayout;
import com.android.systemui.R;
import com.android.systemui.recents.BakedBezierInterpolator;
+import com.android.systemui.recents.Constants;
+import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.Utilities;
+import com.android.systemui.recents.model.Task;
/* The task info view */
@@ -143,6 +148,25 @@
.start();
}
+ /** Binds the info view to the task */
+ void rebindToTask(Task t, boolean animate) {
+ RecentsConfiguration configuration = RecentsConfiguration.getInstance();
+ if (Constants.DebugFlags.App.EnableTaskBarThemeColors && t.colorPrimary != 0) {
+ setBackgroundColor(t.colorPrimary);
+ // Workaround: The button currently doesn't support setting a custom background tint
+ // not defined in the theme. Just lower the alpha on the button to make it blend more
+ // into the background.
+ if (mAppInfoButton.getBackground() instanceof TouchFeedbackDrawable) {
+ TouchFeedbackDrawable d = (TouchFeedbackDrawable) mAppInfoButton.getBackground();
+ if (d != null) {
+ d.setAlpha(96);
+ }
+ }
+ } else {
+ setBackgroundColor(configuration.taskBarViewDefaultBackgroundColor);
+ }
+ }
+
@Override
public void draw(Canvas canvas) {
int saveCount = 0;
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 0a8e76f..ce43b5a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -395,12 +395,20 @@
return false;
}
- /** Returns whether the specified scroll is out of bounds */
- boolean isScrollOutOfBounds(int scroll) {
- return (scroll < mMinScroll) || (scroll > mMaxScroll);
+
+ /** Returns the amount that the scroll is out of bounds */
+ int getScrollAmountOutOfBounds(int scroll) {
+ if (scroll < mMinScroll) {
+ return mMinScroll - scroll;
+ } else if (scroll > mMaxScroll) {
+ return scroll - mMaxScroll;
+ }
+ return 0;
}
+
+ /** Returns whether the specified scroll is out of bounds */
boolean isScrollOutOfBounds() {
- return isScrollOutOfBounds(getStackScroll());
+ return getScrollAmountOutOfBounds(getStackScroll()) != 0;
}
/** Updates the min and max virtual scroll bounds */
@@ -547,7 +555,7 @@
}
/** Computes the stack and task rects */
- public void computeRects(int width, int height, int insetBottom) {
+ public void computeRects(int width, int height, int insetLeft, int insetBottom) {
// Note: We let the stack view be the full height because we want the cards to go under the
// navigation bar if possible. However, the stack rects which we use to calculate
// max scroll, etc. need to take the nav bar into account
@@ -555,12 +563,13 @@
// Compute the stack rects
mRect.set(0, 0, width, height);
mStackRect.set(mRect);
+ mStackRect.left += insetLeft;
mStackRect.bottom -= insetBottom;
int smallestDimension = Math.min(width, height);
int padding = (int) (Constants.Values.TaskStackView.StackPaddingPct * smallestDimension / 2f);
if (Constants.DebugFlags.App.EnableSearchButton) {
- // Don't need to pad the top since we have some padding on the search bar already
+ mStackRect.top += padding;
mStackRect.left += padding;
mStackRect.right -= padding;
mStackRect.bottom -= padding;
@@ -582,6 +591,11 @@
updateMinMaxScroll(false);
}
+ /**
+ * This is called with the size of the space not including the top or right insets, or the
+ * search bar height in portrait (but including the search bar width in landscape, since we want
+ * to draw under it.
+ */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
@@ -592,7 +606,9 @@
// Compute our stack/task rects
RecentsConfiguration config = RecentsConfiguration.getInstance();
- computeRects(width, height, config.systemInsets.bottom);
+ Rect taskStackBounds = new Rect();
+ config.getTaskStackBounds(width, height, taskStackBounds);
+ computeRects(width, height, taskStackBounds.left, config.systemInsets.bottom);
// Debug logging
if (Constants.DebugFlags.UI.MeasureAndLayout) {
@@ -630,6 +646,11 @@
setMeasuredDimension(width, height);
}
+ /**
+ * This is called with the size of the space not including the top or right insets, or the
+ * search bar height in portrait (but including the search bar width in landscape, since we want
+ * to draw under it.
+ */
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
Console.log(Constants.DebugFlags.UI.MeasureAndLayout, "[TaskStackView|layout]",
@@ -1284,9 +1305,13 @@
}
if (mIsScrolling) {
int curStackScroll = mSv.getStackScroll();
- if (mSv.isScrollOutOfBounds(curStackScroll + deltaY)) {
- // Scale the touch if we are overscrolling
- deltaY /= Constants.Values.TaskStackView.TouchOverscrollScaleFactor;
+ int overScrollAmount = mSv.getScrollAmountOutOfBounds(curStackScroll + deltaY);
+ if (overScrollAmount != 0) {
+ // Bound the overscroll to a fixed amount, and inversely scale the y-movement
+ // relative to how close we are to the max overscroll
+ float maxOverScroll = mSv.mTaskRect.height() / 3f;
+ deltaY = Math.round(deltaY * (1f - (Math.min(maxOverScroll, overScrollAmount)
+ / maxOverScroll)));
}
mSv.setStackScroll(curStackScroll + deltaY);
if (mSv.isScrollOutOfBounds()) {
@@ -1306,6 +1331,7 @@
if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
// Enable HW layers on the stack
mSv.addHwLayersRefCount("flingScroll");
+ // XXX: Make this animation a function of the velocity AND distance
int overscrollRange = (int) (Math.min(1f,
Math.abs((float) velocity / mMaximumVelocity)) *
Constants.Values.TaskStackView.TaskStackOverscrollRange);
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 d3b79d6..801de24 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -20,6 +20,7 @@
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.Outline;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
@@ -33,7 +34,6 @@
import com.android.systemui.recents.BakedBezierInterpolator;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.Utilities;
import com.android.systemui.recents.model.Task;
@@ -108,6 +108,11 @@
mRoundedRectClipPath.reset();
mRoundedRectClipPath.addRoundRect(new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight()),
radius, radius, Path.Direction.CW);
+
+ // Update the outline
+ Outline o = new Outline();
+ o.setRoundRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), radius);
+ setOutline(o);
}
@Override
@@ -134,14 +139,20 @@
/** Synchronizes this view's properties with the task's transform */
void updateViewPropertiesToTaskTransform(TaskViewTransform animateFromTransform,
TaskViewTransform toTransform, int duration) {
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ int minZ = config.taskViewTranslationZMinPx;
+ int incZ = config.taskViewTranslationZIncrementPx;
+
if (duration > 0) {
if (animateFromTransform != null) {
setTranslationY(animateFromTransform.translationY);
+ setTranslationZ(Math.max(minZ, minZ + (animateFromTransform.t * incZ)));
setScaleX(animateFromTransform.scale);
setScaleY(animateFromTransform.scale);
setAlpha(animateFromTransform.alpha);
}
animate().translationY(toTransform.translationY)
+ .translationZ(Math.max(minZ, minZ + (toTransform.t * incZ)))
.scaleX(toTransform.scale)
.scaleY(toTransform.scale)
.alpha(toTransform.alpha)
@@ -157,6 +168,7 @@
.start();
} else {
setTranslationY(toTransform.translationY);
+ setTranslationZ(Math.max(minZ, minZ + (toTransform.t * incZ)));
setScaleX(toTransform.scale);
setScaleY(toTransform.scale);
setAlpha(toTransform.alpha);
@@ -169,6 +181,7 @@
void resetViewProperties() {
setTranslationX(0f);
setTranslationY(0f);
+ setTranslationZ(0f);
setScaleX(1f);
setScaleY(1f);
setAlpha(1f);
@@ -197,18 +210,9 @@
/** Animates this task view as it enters recents */
public void animateOnEnterRecents() {
RecentsConfiguration config = RecentsConfiguration.getInstance();
- int translate = config.pxFromDp(10);
- mBarView.setScaleX(1.25f);
- mBarView.setScaleY(1.25f);
mBarView.setAlpha(0f);
- mBarView.setTranslationX(translate / 2);
- mBarView.setTranslationY(-translate);
mBarView.animate()
.alpha(1f)
- .scaleX(1f)
- .scaleY(1f)
- .translationX(0)
- .translationY(0)
.setStartDelay(235)
.setInterpolator(BakedBezierInterpolator.INSTANCE)
.setDuration(config.taskBarEnterAnimDuration)
@@ -219,16 +223,11 @@
/** Animates this task view as it exits recents */
public void animateOnLeavingRecents(final Runnable r) {
RecentsConfiguration config = RecentsConfiguration.getInstance();
- int translate = config.pxFromDp(10);
mBarView.animate()
.alpha(0f)
- .scaleX(1.1f)
- .scaleY(1.1f)
- .translationX(translate / 2)
- .translationY(-translate)
.setStartDelay(0)
.setInterpolator(BakedBezierInterpolator.INSTANCE)
- .setDuration(Utilities.calculateTranslationAnimationDuration(translate))
+ .setDuration(config.taskBarExitAnimDuration)
.withLayer()
.withEndAction(new Runnable() {
@Override
@@ -352,6 +351,7 @@
// Bind each of the views to the new task data
mThumbnailView.rebindToTask(mTask, reloadingTaskData);
mBarView.rebindToTask(mTask, reloadingTaskData);
+ mInfoView.rebindToTask(mTask, reloadingTaskData);
// Rebind any listeners
mBarView.mApplicationIcon.setOnClickListener(this);
mInfoView.mAppInfoButton.setOnClickListener(this);
@@ -376,7 +376,7 @@
@Override
public void onClick(View v) {
if (v == mInfoView) {
- // Do nothing
+ hideInfoPane();
} else if (v == mBarView.mApplicationIcon) {
mCb.onTaskIconClicked(this);
} else if (v == mInfoView.mAppInfoButton) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index edf54d1..2c7464a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -773,8 +773,8 @@
PendingIntent contentIntent = sbn.getNotification().contentIntent;
if (contentIntent != null) {
- final View.OnClickListener listener = makeClicker(contentIntent,
- sbn.getPackageName(), sbn.getTag(), sbn.getId(), isHeadsUp, sbn.getUserId());
+ final View.OnClickListener listener = makeClicker(contentIntent, sbn.getKey(),
+ isHeadsUp);
row.setOnClickListener(listener);
} else {
row.setOnClickListener(null);
@@ -884,27 +884,20 @@
return true;
}
- public NotificationClicker makeClicker(PendingIntent intent, String pkg, String tag,
- int id, boolean forHun, int userId) {
- return new NotificationClicker(intent, pkg, tag, id, forHun, userId);
+ public NotificationClicker makeClicker(PendingIntent intent, String notificationKey,
+ boolean forHun) {
+ return new NotificationClicker(intent, notificationKey, forHun);
}
protected class NotificationClicker implements View.OnClickListener {
private PendingIntent mIntent;
- private String mPkg;
- private String mTag;
- private int mId;
+ private final String mNotificationKey;
private boolean mIsHeadsUp;
- private int mUserId;
- public NotificationClicker(PendingIntent intent, String pkg, String tag, int id,
- boolean forHun, int userId) {
+ public NotificationClicker(PendingIntent intent, String notificationKey, boolean forHun) {
mIntent = intent;
- mPkg = pkg;
- mTag = tag;
- mId = id;
+ mNotificationKey = notificationKey;
mIsHeadsUp = forHun;
- mUserId = userId;
}
public void onClick(View v) {
@@ -940,7 +933,7 @@
if (mIsHeadsUp) {
mHandler.sendEmptyMessage(MSG_HIDE_HEADS_UP);
}
- mBarService.onNotificationClick(mPkg, mTag, mId, mUserId);
+ mBarService.onNotificationClick(mNotificationKey);
} catch (RemoteException ex) {
// system process is dead if we're here.
}
@@ -1344,9 +1337,8 @@
// update the contentIntent
final PendingIntent contentIntent = notification.getNotification().contentIntent;
if (contentIntent != null) {
- final View.OnClickListener listener = makeClicker(contentIntent,
- notification.getPackageName(), notification.getTag(), notification.getId(),
- isHeadsUp, notification.getUserId());
+ final View.OnClickListener listener = makeClicker(contentIntent, notification.getKey(),
+ isHeadsUp);
entry.row.setOnClickListener(listener);
} else {
entry.row.setOnClickListener(null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 232795a..169521d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.util.AttributeSet;
+import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
@@ -44,6 +45,19 @@
mActualHeightInitialized = true;
}
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ if (filterMotionEvent(ev)) {
+ return super.dispatchTouchEvent(ev);
+ }
+ return false;
+ }
+
+ private boolean filterMotionEvent(MotionEvent event) {
+ return event.getActionMasked() != MotionEvent.ACTION_DOWN
+ || event.getY() > mClipTopAmount && event.getY() < mActualHeight;
+ }
+
/**
* Sets the actual height of this notification. This is different than the laid out
* {@link View#getHeight()}, as we want to avoid layouting during scrolling and expanding.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
new file mode 100644
index 0000000..5bc7e5a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
@@ -0,0 +1,28 @@
+/*
+ * 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.phone;
+
+import android.content.Intent;
+
+/**
+ * An interface to start activities. This is used to as a callback from the views to
+ * {@link PhoneStatusBar} to allow custom handling for starting the activity, i.e. dismissing the
+ * Keyguard.
+ */
+public interface ActivityStarter {
+ public void startActivity(Intent intent);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 3cc22ef..58b3f2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -42,14 +43,18 @@
* Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
* text.
*/
-public class KeyguardBottomAreaView extends FrameLayout {
+public class KeyguardBottomAreaView extends FrameLayout
+ implements SwipeAffordanceView.AffordanceListener {
final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
- private View mCameraButton;
- private float mCameraDragDistance;
+ private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL);
+
+ private SwipeAffordanceView mCameraButton;
+ private SwipeAffordanceView mPhoneButton;
+
private PowerManager mPowerManager;
- private int mScaledTouchSlop;
+ private ActivityStarter mActivityStarter;
public KeyguardBottomAreaView(Context context) {
super(context);
@@ -71,20 +76,37 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mCameraButton = findViewById(R.id.camera_button);
+ mCameraButton = (SwipeAffordanceView) findViewById(R.id.camera_button);
+ mPhoneButton = (SwipeAffordanceView) findViewById(R.id.phone_button);
+ mCameraButton.setAffordanceListener(this);
+ mPhoneButton.setAffordanceListener(this);
watchForDevicePolicyChanges();
watchForAccessibilityChanges();
updateCameraVisibility();
- mCameraDragDistance = getResources().getDimension(R.dimen.camera_drag_distance);
- mScaledTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+ updatePhoneVisibility();
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
}
+ public void setActivityStarter(ActivityStarter activityStarter) {
+ mActivityStarter = activityStarter;
+ }
+
private void updateCameraVisibility() {
boolean visible = !isCameraDisabledByDpm();
mCameraButton.setVisibility(visible ? View.VISIBLE : View.GONE);
}
+ private void updatePhoneVisibility() {
+ boolean visible = isPhoneVisible();
+ mPhoneButton.setVisibility(visible ? View.VISIBLE : View.GONE);
+ }
+
+ private boolean isPhoneVisible() {
+ PackageManager pm = mContext.getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
+ && pm.resolveActivity(PHONE_INTENT, 0) != null;
+ }
+
private boolean isCameraDisabledByDpm() {
final DevicePolicyManager dpm =
(DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
@@ -136,15 +158,8 @@
}
private void enableAccessibility(boolean touchExplorationEnabled) {
-
- // Add a touch handler or accessibility click listener for camera button.
- if (touchExplorationEnabled) {
- mCameraButton.setOnTouchListener(null);
- mCameraButton.setOnClickListener(mCameraClickListener);
- } else {
- mCameraButton.setOnTouchListener(mCameraTouchListener);
- mCameraButton.setOnClickListener(null);
- }
+ mCameraButton.enableAccessibility(touchExplorationEnabled);
+ mPhoneButton.enableAccessibility(touchExplorationEnabled);
}
private void launchCamera() {
@@ -153,80 +168,21 @@
UserHandle.CURRENT);
}
- private final OnClickListener mCameraClickListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
+ private void launchPhone() {
+ mActivityStarter.startActivity(PHONE_INTENT);
+ }
+
+ @Override
+ public void onUserActivity(long when) {
+ mPowerManager.userActivity(when, false);
+ }
+
+ @Override
+ public void onActionPerformed(SwipeAffordanceView view) {
+ if (view == mCameraButton) {
launchCamera();
+ } else if (view == mPhoneButton) {
+ launchPhone();
}
- };
-
- private final OnTouchListener mCameraTouchListener = new OnTouchListener() {
- private float mStartX;
- private boolean mTouchSlopReached;
- private boolean mSkipCancelAnimation;
-
- @Override
- public boolean onTouch(final View cameraButtonView, MotionEvent event) {
- float realX = event.getRawX();
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mStartX = realX;
- mTouchSlopReached = false;
- mSkipCancelAnimation = false;
- break;
- case MotionEvent.ACTION_MOVE:
- if (realX > mStartX) {
- realX = mStartX;
- }
- if (realX < mStartX - mCameraDragDistance) {
- cameraButtonView.setPressed(true);
- mPowerManager.userActivity(event.getEventTime(), false);
- } else {
- cameraButtonView.setPressed(false);
- }
- if (realX < mStartX - mScaledTouchSlop) {
- mTouchSlopReached = true;
- }
- cameraButtonView.setTranslationX(Math.max(realX - mStartX,
- -mCameraDragDistance));
- break;
- case MotionEvent.ACTION_UP:
- if (realX < mStartX - mCameraDragDistance) {
- launchCamera();
- cameraButtonView.animate().x(-cameraButtonView.getWidth())
- .setInterpolator(new AccelerateInterpolator(2f)).withEndAction(
- new Runnable() {
- @Override
- public void run() {
- cameraButtonView.setTranslationX(0);
- }
- });
- mSkipCancelAnimation = true;
- }
- if (realX < mStartX - mScaledTouchSlop) {
- mTouchSlopReached = true;
- }
- if (!mTouchSlopReached) {
- mSkipCancelAnimation = true;
- cameraButtonView.animate().translationX(-mCameraDragDistance / 2).
- setInterpolator(new DecelerateInterpolator()).withEndAction(
- new Runnable() {
- @Override
- public void run() {
- cameraButtonView.animate().translationX(0).
- setInterpolator(new AccelerateInterpolator());
- }
- });
- }
- case MotionEvent.ACTION_CANCEL:
- cameraButtonView.setPressed(false);
- if (!mSkipCancelAnimation) {
- cameraButtonView.animate().translationX(0)
- .setInterpolator(new AccelerateInterpolator(2f));
- }
- break;
- }
- return true;
- }
- };
+ }
}
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 328a172..0cdca66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -623,9 +623,7 @@
mExpandedHeight = mMaxPanelHeight;
}
}
- heightMeasureSpec = MeasureSpec.makeMeasureSpec(
- getDesiredMeasureHeight(), MeasureSpec.AT_MOST);
- setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
+ setMeasuredDimension(getMeasuredWidth(), getDesiredMeasureHeight());
}
protected int getDesiredMeasureHeight() {
@@ -705,11 +703,6 @@
* @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 mMaxPanelHeight;
}
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 0db6914..f945c79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -124,7 +124,7 @@
import java.util.Collections;
public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
- DragDownHelper.OnDragDownListener {
+ DragDownHelper.OnDragDownListener, ActivityStarter {
static final String TAG = "PhoneStatusBar";
public static final boolean DEBUG = BaseStatusBar.DEBUG;
public static final boolean SPEW = false;
@@ -236,7 +236,7 @@
// top bar
View mNotificationPanelHeader;
View mKeyguardStatusView;
- View mKeyguardBottomArea;
+ KeyguardBottomAreaView mKeyguardBottomArea;
boolean mLeaveOpenOnKeyguardHide;
KeyguardIndicationTextView mKeyguardIndicationTextView;
@@ -639,7 +639,9 @@
mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header);
mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
- mKeyguardBottomArea = mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
+ mKeyguardBottomArea =
+ (KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
+ mKeyguardBottomArea.setActivityStarter(this);
mKeyguardIndicationTextView = (KeyguardIndicationTextView) mStatusBarWindow.findViewById(
R.id.keyguard_indication_text);
mClearButton = mStatusBarWindow.findViewById(R.id.clear_all_button);
@@ -1578,6 +1580,11 @@
return new PhoneStatusBar.H();
}
+ @Override
+ public void startActivity(Intent intent) {
+ startActivityDismissingKeyguard(intent, false);
+ }
+
/**
* All changes to the status bar and notifications funnel through here and are batched.
*/
@@ -1668,6 +1675,9 @@
}
public void animateCollapsePanels(int flags) {
+ if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
+ return;
+ }
if (SPEW) {
Log.d(TAG, "animateCollapse():"
+ " mExpandedVisible=" + mExpandedVisible
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 554892c..e24ddd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -205,10 +205,12 @@
} else {
mContainer.setSystemUiVisibility(vis | View.STATUS_BAR_DISABLE_BACK);
}
- if (!(mShowing && !mOccluded) || mBouncer.isShowing()) {
- mPhoneStatusBar.getNavigationBarView().setVisibility(View.VISIBLE);
- } else {
- mPhoneStatusBar.getNavigationBarView().setVisibility(View.GONE);
+ if (mPhoneStatusBar.getNavigationBarView() != null) {
+ if (!(mShowing && !mOccluded) || mBouncer.isShowing()) {
+ mPhoneStatusBar.getNavigationBarView().setVisibility(View.VISIBLE);
+ } else {
+ mPhoneStatusBar.getNavigationBarView().setVisibility(View.GONE);
+ }
}
mPhoneStatusBar.setBouncerShowing(mBouncer.isShowing());
}
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 acc3a0b..4c9264d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -108,7 +108,9 @@
boolean intercept = false;
if (mNotificationPanel.isFullyExpanded()
&& mStackScrollLayout.getVisibility() == View.VISIBLE
- && mService.getBarState() != StatusBarState.KEYGUARD) {
+ && (mService.getBarState() == StatusBarState.SHADE
+ || (mService.getBarState() == StatusBarState.SHADE_LOCKED
+ && !mService.isBouncerShowing()))) {
intercept = mExpandHelper.onInterceptTouchEvent(ev);
} else if (mNotificationPanel.isFullyExpanded()
&& mStackScrollLayout.getVisibility() == View.VISIBLE
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SwipeAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SwipeAffordanceView.java
new file mode 100644
index 0000000..049c5fc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SwipeAffordanceView.java
@@ -0,0 +1,222 @@
+/*
+ * 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.phone;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.SystemClock;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.Button;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.KeyButtonView;
+
+/**
+ * A swipeable button for affordances on the lockscreen. This is used for the camera and phone
+ * affordance.
+ */
+public class SwipeAffordanceView extends KeyButtonView {
+
+ private static final int SWIPE_DIRECTION_START = 0;
+ private static final int SWIPE_DIRECTION_END = 1;
+
+ private static final int SWIPE_DIRECTION_LEFT = 0;
+ private static final int SWIPE_DIRECTION_RIGHT = 1;
+
+ private AffordanceListener mListener;
+ private int mScaledTouchSlop;
+ private float mDragDistance;
+ private int mResolvedSwipeDirection;
+ private int mSwipeDirection;
+
+ public SwipeAffordanceView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public SwipeAffordanceView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ TypedArray a = context.getTheme().obtainStyledAttributes(
+ attrs,
+ R.styleable.SwipeAffordanceView,
+ 0, 0);
+ try {
+ mSwipeDirection = a.getInt(R.styleable.SwipeAffordanceView_swipeDirection, 0);
+ } finally {
+ a.recycle();
+ }
+ }
+
+ @Override
+ public void onRtlPropertiesChanged(int layoutDirection) {
+ super.onRtlPropertiesChanged(layoutDirection);
+ if (!isLayoutRtl()) {
+ mResolvedSwipeDirection = mSwipeDirection;
+ } else {
+ mResolvedSwipeDirection = mSwipeDirection == SWIPE_DIRECTION_START
+ ? SWIPE_DIRECTION_RIGHT
+ : SWIPE_DIRECTION_LEFT;
+ }
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mDragDistance = getResources().getDimension(R.dimen.affordance_drag_distance);
+ mScaledTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+ }
+
+ public void enableAccessibility(boolean touchExplorationEnabled) {
+
+ // Add a touch handler or accessibility click listener for camera button.
+ if (touchExplorationEnabled) {
+ setOnTouchListener(null);
+ setOnClickListener(mClickListener);
+ } else {
+ setOnTouchListener(mTouchListener);
+ setOnClickListener(null);
+ }
+ }
+
+ public void setAffordanceListener(AffordanceListener listener) {
+ mListener = listener;
+ }
+
+ private void onActionPerformed() {
+ if (mListener != null) {
+ mListener.onActionPerformed(this);
+ }
+ }
+
+ private void onUserActivity(long when) {
+ if (mListener != null) {
+ mListener.onUserActivity(when);
+ }
+ }
+
+ private final OnClickListener mClickListener = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onActionPerformed();
+ }
+ };
+
+ private final OnTouchListener mTouchListener = new OnTouchListener() {
+ private float mStartX;
+ private boolean mTouchSlopReached;
+ private boolean mSkipCancelAnimation;
+
+ @Override
+ public boolean onTouch(final View view, MotionEvent event) {
+ float realX = event.getRawX();
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mStartX = realX;
+ mTouchSlopReached = false;
+ mSkipCancelAnimation = false;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+ ? realX > mStartX
+ : realX < mStartX) {
+ realX = mStartX;
+ }
+ if (mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+ ? realX < mStartX - mDragDistance
+ : realX > mStartX + mDragDistance) {
+ view.setPressed(true);
+ onUserActivity(event.getEventTime());
+ } else {
+ view.setPressed(false);
+ }
+ if (mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+ ? realX < mStartX - mScaledTouchSlop
+ : realX > mStartX + mScaledTouchSlop) {
+ mTouchSlopReached = true;
+ }
+ view.setTranslationX(mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+ ? Math.max(realX - mStartX, -mDragDistance)
+ : Math.min(realX - mStartX, mDragDistance));
+ break;
+ case MotionEvent.ACTION_UP:
+ if (mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+ ? realX < mStartX - mDragDistance
+ : realX > mStartX + mDragDistance) {
+ onActionPerformed();
+ view.animate().x(mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+ ? -view.getWidth()
+ : ((View) view.getParent()).getWidth() + view.getWidth())
+ .setInterpolator(new AccelerateInterpolator(2f)).withEndAction(
+ new Runnable() {
+ @Override
+ public void run() {
+ view.setTranslationX(0);
+ }
+ });
+ mSkipCancelAnimation = true;
+ }
+ if (mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+ ? realX < mStartX - mScaledTouchSlop
+ : realX > mStartX + mScaledTouchSlop) {
+ mTouchSlopReached = true;
+ }
+ if (!mTouchSlopReached) {
+ mSkipCancelAnimation = true;
+ view.animate().translationX(mResolvedSwipeDirection == SWIPE_DIRECTION_LEFT
+ ? -mDragDistance / 2
+ : mDragDistance / 2).
+ setInterpolator(new DecelerateInterpolator()).withEndAction(
+ new Runnable() {
+ @Override
+ public void run() {
+ view.animate().translationX(0).
+ setInterpolator(new AccelerateInterpolator());
+ }
+ });
+ }
+ case MotionEvent.ACTION_CANCEL:
+ view.setPressed(false);
+ if (!mSkipCancelAnimation) {
+ view.animate().translationX(0)
+ .setInterpolator(new AccelerateInterpolator(2f));
+ }
+ break;
+ }
+ return true;
+ }
+ };
+
+ public interface AffordanceListener {
+
+ /**
+ * Called when the view would like to report user activity.
+ *
+ * @param when The timestamp of the user activity in {@link SystemClock#uptimeMillis} time
+ * base.
+ */
+ void onUserActivity(long when);
+
+ /**
+ * Called when the action of the affordance has been performed.
+ */
+ void onActionPerformed(SwipeAffordanceView view);
+ }
+}
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 20011ff..ff921cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
@@ -356,7 +356,7 @@
@Override
public boolean onTouchEvent(MotionEvent event) {
- log("onTouchEvent " + MotionEvent.actionToString(event.getAction()));
+ if (DEBUG) log("onTouchEvent " + MotionEvent.actionToString(event.getAction()));
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mDownX = event.getX();
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 50e2a2e..b1fea03 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -3560,15 +3560,7 @@
swipeDismiss.setOnDismissedListener(new SwipeDismissLayout.OnDismissedListener() {
@Override
public void onDismissed(SwipeDismissLayout layout) {
- Callback cb = getCallback();
- if (cb != null) {
- try {
- cb.onWindowDismissed();
- } catch (AbstractMethodError e) {
- Log.e(TAG, "onWindowDismissed not implemented in " +
- cb.getClass().getSimpleName(), e);
- }
- }
+ dispatchOnWindowDismissed();
}
});
swipeDismiss.setOnSwipeProgressChangedListener(
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 761e580..ae6aeee 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -667,7 +667,8 @@
private void interceptPowerKeyDown(boolean handled) {
mPowerKeyHandled = handled;
if (!handled) {
- mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
+ mHandler.postDelayed(mPowerLongPress,
+ ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
}
}
@@ -706,9 +707,9 @@
if (mKeyguardDelegate.isShowing()) {
// Double the time it takes to take a screenshot from the keyguard
return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER *
- ViewConfiguration.getGlobalActionKeyTimeout());
+ ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
}
- return ViewConfiguration.getGlobalActionKeyTimeout();
+ return ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout();
}
private void cancelPendingScreenshotChordAction() {
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
index 77d5076..2fa23c9 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
@@ -125,8 +125,10 @@
// Register for the boot completed broadcast, so we can send the
// ENABLE broacasts. If we try to send them now, they time out,
// because the system isn't ready to handle them yet.
+ IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
- new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+ filter, null, null);
// Register for configuration changes so we can update the names
// of the widgets when the locale changes.
@@ -135,7 +137,6 @@
// Register for broadcasts about package install, etc., so we can
// update the provider list.
- IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 0d6f548..e2a8ca2 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -212,6 +212,7 @@
filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
registerForAirplaneMode(filter);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(mReceiver, filter);
loadStoredNameAndAddress();
if (isBluetoothPersistedStateOn()) {
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 5083d44..6fab37c2 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -65,6 +65,8 @@
27501 notification_panel_hidden
# when notifications are newly displayed on screen, or disappear from screen
27510 notification_visibility_changed (newlyVisibleKeys|3),(noLongerVisibleKeys|3)
+# when a notification has been clicked
+27520 notification_clicked (key|3)
# ---------------------------
# Watchdog.java
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 6fc3e77..7ed1cc7 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1548,7 +1548,8 @@
mImeSwitcherNotification.setLatestEventInfo(
mContext, title, summary, mImeSwitchPendingIntent);
- if (mNotificationManager != null) {
+ if ((mNotificationManager != null)
+ && !mWindowManagerService.hasNavigationBar()) {
if (DEBUG) {
Slog.d(TAG, "--- show notification: label = " + summary);
}
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 8a30e50..4f0c9b5 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -20,19 +20,24 @@
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
+import android.net.INetworkScoreCache;
import android.net.INetworkScoreService;
-import android.net.NetworkKey;
import android.net.NetworkScorerAppManager;
-import android.net.RssiCurve;
import android.net.ScoredNetwork;
+import android.os.RemoteException;
import android.text.TextUtils;
+import android.util.Log;
import com.android.internal.R;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Backing service for {@link android.net.NetworkScoreManager}.
@@ -46,12 +51,11 @@
private final Context mContext;
- // TODO: Delete this temporary class once we have a real place for scores.
- private final Map<NetworkKey, RssiCurve> mScoredNetworks;
+ private final Map<Integer, INetworkScoreCache> mScoreCaches;
public NetworkScoreService(Context context) {
mContext = context;
- mScoredNetworks = new HashMap<>();
+ mScoreCaches = new HashMap<>();
}
/** Called when the system is ready to run third-party code but before it actually does so. */
@@ -76,10 +80,31 @@
" is not the active scorer.");
}
- // TODO: Propagate these scores down to the network subsystem layer instead of just holding
- // them in memory.
+ // Separate networks by type.
+ Map<Integer, List<ScoredNetwork>> networksByType = new HashMap<>();
for (ScoredNetwork network : networks) {
- mScoredNetworks.put(network.networkKey, network.rssiCurve);
+ List<ScoredNetwork> networkList = networksByType.get(network.networkKey.type);
+ if (networkList == null) {
+ networkList = new ArrayList<>();
+ networksByType.put(network.networkKey.type, networkList);
+ }
+ networkList.add(network);
+ }
+
+ // Pass the scores of each type down to the appropriate network scorer.
+ for (Map.Entry<Integer, List<ScoredNetwork>> entry : networksByType.entrySet()) {
+ INetworkScoreCache scoreCache = mScoreCaches.get(entry.getKey());
+ if (scoreCache != null) {
+ try {
+ scoreCache.updateScores(entry.getValue());
+ } catch (RemoteException e) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Unable to update scores of type " + entry.getKey(), e);
+ }
+ }
+ } else if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "No scorer registered for type " + entry.getKey() + ", discarding");
+ }
}
return true;
@@ -112,8 +137,29 @@
/** Clear scores. Callers are responsible for checking permissions as appropriate. */
private void clearInternal() {
- // TODO: Propagate the flush down to the network subsystem layer.
- mScoredNetworks.clear();
+ Set<INetworkScoreCache> cachesToClear = getScoreCaches();
+
+ for (INetworkScoreCache scoreCache : cachesToClear) {
+ try {
+ scoreCache.clearScores();
+ } catch (RemoteException e) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Unable to clear scores", e);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
+ mContext.enforceCallingOrSelfPermission(permission.BROADCAST_SCORE_NETWORKS, TAG);
+ synchronized (mScoreCaches) {
+ if (mScoreCaches.containsKey(networkType)) {
+ throw new IllegalArgumentException(
+ "Score cache already registered for type " + networkType);
+ }
+ mScoreCaches.put(networkType, scoreCache);
+ }
}
@Override
@@ -125,12 +171,28 @@
return;
}
writer.println("Current scorer: " + currentScorer);
- if (mScoredNetworks.isEmpty()) {
- writer.println("No networks scored.");
- } else {
- for (Map.Entry<NetworkKey, RssiCurve> entry : mScoredNetworks.entrySet()) {
- writer.println(entry.getKey() + ": " + entry.getValue());
+
+ for (INetworkScoreCache scoreCache : getScoreCaches()) {
+ try {
+ scoreCache.asBinder().dump(fd, args);
+ } catch (RemoteException e) {
+ writer.println("Unable to dump score cache");
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Unable to dump score cache", e);
+ }
}
}
}
+
+ /**
+ * Returns a set of all score caches that are currently active.
+ *
+ * <p>May be used to perform an action on all score caches without potentially strange behavior
+ * if a new scorer is registered during that action's execution.
+ */
+ private Set<INetworkScoreCache> getScoreCaches() {
+ synchronized (mScoreCaches) {
+ return new HashSet<>(mScoreCaches.values());
+ }
+ }
}
diff --git a/services/core/java/com/android/server/RecognitionManagerService.java b/services/core/java/com/android/server/RecognitionManagerService.java
index c2e749d..60d38ae 100644
--- a/services/core/java/com/android/server/RecognitionManagerService.java
+++ b/services/core/java/com/android/server/RecognitionManagerService.java
@@ -78,8 +78,10 @@
mMonitor = new MyPackageMonitor();
mMonitor.register(context, null, UserHandle.ALL, true);
mIPm = AppGlobals.getPackageManager();
+ IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
- new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+ filter, null, null);
}
public void systemReady() {
diff --git a/services/core/java/com/android/server/WiredAccessoryManager.java b/services/core/java/com/android/server/WiredAccessoryManager.java
index 415fcc1..50cfe48 100644
--- a/services/core/java/com/android/server/WiredAccessoryManager.java
+++ b/services/core/java/com/android/server/WiredAccessoryManager.java
@@ -97,13 +97,15 @@
mObserver = new WiredAccessoryObserver();
+ IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
context.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context ctx, Intent intent) {
bootCompleted();
}
},
- new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, null);
+ filter, null, null);
}
private void bootCompleted() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9eaddbd..cbb8377 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -95,7 +95,6 @@
import android.app.IProcessObserver;
import android.app.IServiceConnection;
import android.app.IStopUserCallback;
-import android.app.IThumbnailReceiver;
import android.app.IUiAutomationConnection;
import android.app.IUserSwitchObserver;
import android.app.Instrumentation;
@@ -703,13 +702,6 @@
String mBackupAppName = null;
BackupRecord mBackupTarget = null;
- /**
- * List of PendingThumbnailsRecord objects of clients who are still
- * waiting to receive all of the thumbnails for a task.
- */
- final ArrayList<PendingThumbnailsRecord> mPendingThumbnails =
- new ArrayList<PendingThumbnailsRecord>();
-
final ProviderMap mProviderMap;
/**
@@ -5452,21 +5444,15 @@
throw new IllegalArgumentException("File descriptors passed in Bundle");
}
- ActivityRecord r = null;
-
final long origId = Binder.clearCallingIdentity();
synchronized (this) {
- r = ActivityRecord.isInStackLocked(token);
+ ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r != null) {
r.task.stack.activityStoppedLocked(r, icicle, thumbnail, description);
}
}
- if (r != null) {
- sendPendingThumbnail(r, null, null, null, false);
- }
-
trimApplications();
Binder.restoreCallingIdentity(origId);
@@ -6982,66 +6968,24 @@
// =========================================================
@Override
- public List<RunningTaskInfo> getTasks(int maxNum, int flags,
- IThumbnailReceiver receiver) {
+ public List<RunningTaskInfo> getTasks(int maxNum, int flags) {
+ final int callingUid = Binder.getCallingUid();
ArrayList<RunningTaskInfo> list = new ArrayList<RunningTaskInfo>();
- PendingThumbnailsRecord pending = new PendingThumbnailsRecord(receiver);
- ActivityRecord topRecord = null;
-
synchronized(this) {
if (localLOGV) Slog.v(
- TAG, "getTasks: max=" + maxNum + ", flags=" + flags
- + ", receiver=" + receiver);
+ TAG, "getTasks: max=" + maxNum + ", flags=" + flags);
- if (checkCallingPermission(android.Manifest.permission.GET_TASKS)
- != PackageManager.PERMISSION_GRANTED) {
- if (receiver != null) {
- // If the caller wants to wait for pending thumbnails,
- // it ain't gonna get them.
- try {
- receiver.finished();
- } catch (RemoteException ex) {
- }
- }
- String msg = "Permission Denial: getTasks() from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid()
- + " requires " + android.Manifest.permission.GET_TASKS;
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
+ final boolean allowed = checkCallingPermission(
+ android.Manifest.permission.GET_TASKS)
+ == PackageManager.PERMISSION_GRANTED;
+ if (!allowed) {
+ Slog.w(TAG, "getTasks: caller " + callingUid
+ + " does not hold GET_TASKS; limiting output");
}
// TODO: Improve with MRU list from all ActivityStacks.
- topRecord = mStackSupervisor.getTasksLocked(maxNum, receiver, pending, list);
-
- if (!pending.pendingRecords.isEmpty()) {
- mPendingThumbnails.add(pending);
- }
- }
-
- if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
-
- if (topRecord != null) {
- if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
- try {
- IApplicationThread topThumbnail = topRecord.app.thread;
- topThumbnail.requestThumbnail(topRecord.appToken);
- } catch (Exception e) {
- Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
- sendPendingThumbnail(null, topRecord.appToken, null, null, true);
- }
- }
-
- if (pending.pendingRecords.isEmpty() && receiver != null) {
- // In this case all thumbnails were available and the client
- // is being asked to be told when the remaining ones come in...
- // which is unusually, since the top-most currently running
- // activity should never have a canned thumbnail! Oh well.
- try {
- receiver.finished();
- } catch (RemoteException ex) {
- }
+ mStackSupervisor.getTasksLocked(maxNum, list, callingUid, allowed);
}
return list;
@@ -7054,12 +6998,18 @@
@Override
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
int flags, int userId) {
- userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+ final int callingUid = Binder.getCallingUid();
+ userId = handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
false, true, "getRecentTasks", null);
synchronized (this) {
- enforceCallingPermission(android.Manifest.permission.GET_TASKS,
- "getRecentTasks()");
+ final boolean allowed = checkCallingPermission(
+ android.Manifest.permission.GET_TASKS)
+ == PackageManager.PERMISSION_GRANTED;
+ if (!allowed) {
+ Slog.w(TAG, "getRecentTasks: caller " + callingUid
+ + " does not hold GET_TASKS; limiting output");
+ }
final boolean detailed = checkCallingPermission(
android.Manifest.permission.GET_DETAILED_TASKS)
== PackageManager.PERMISSION_GRANTED;
@@ -7094,6 +7044,13 @@
|| (tr.intent == null)
|| ((tr.intent.getFlags()
&Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)) {
+ if (!allowed) {
+ // If the caller doesn't have the GET_TASKS permission, then only
+ // allow them to see a small subset of tasks -- their own and home.
+ if (!tr.isHomeTask() && tr.creatorUid != callingUid) {
+ continue;
+ }
+ }
ActivityManager.RecentTaskInfo rti
= new ActivityManager.RecentTaskInfo();
rti.id = tr.numActivities > 0 ? tr.taskId : -1;
@@ -7122,14 +7079,34 @@
break;
}
}
- // Traverse downwards starting below break looking for set label and icon.
- for (--activityNdx; activityNdx >= 0; --activityNdx) {
- final ActivityRecord r = activities.get(activityNdx);
- if (r.activityLabel != null || r.activityIcon != null) {
- rti.activityLabel = r.activityLabel;
- rti.activityIcon = r.activityIcon;
- break;
+ if (activityNdx > 0) {
+ // Traverse downwards starting below break looking for set label, icon.
+ // Note that if there are activities in the task but none of them set the
+ // recent activity values, then we do not fall back to the last set
+ // values in the TaskRecord.
+ rti.activityValues = new ActivityManager.RecentsActivityValues();
+ for (--activityNdx; activityNdx >= 0; --activityNdx) {
+ final ActivityRecord r = activities.get(activityNdx);
+ if (r.activityValues != null) {
+ if (rti.activityValues.label == null) {
+ rti.activityValues.label = r.activityValues.label;
+ tr.lastActivityValues.label = r.activityValues.label;
+ }
+ if (rti.activityValues.icon == null) {
+ rti.activityValues.icon = r.activityValues.icon;
+ tr.lastActivityValues.icon = r.activityValues.icon;
+ }
+ if (rti.activityValues.colorPrimary == 0) {
+ rti.activityValues.colorPrimary = r.activityValues.colorPrimary;
+ tr.lastActivityValues.colorPrimary = r.activityValues.colorPrimary;
+ }
+ }
}
+ } else {
+ // If there are no activity records in this task, then we use the last
+ // resolved values
+ rti.activityValues =
+ new ActivityManager.RecentsActivityValues(tr.lastActivityValues);
}
if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0) {
@@ -7197,13 +7174,11 @@
}
@Override
- public void setActivityLabelAndIcon(IBinder token, CharSequence activityLabel,
- Bitmap activityIcon) {
+ public void setRecentsActivityValues(IBinder token, ActivityManager.RecentsActivityValues rav) {
synchronized (this) {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r != null) {
- r.activityLabel = activityLabel.toString();
- r.activityIcon = activityIcon;
+ r.activityValues = rav;
}
}
}
@@ -7635,82 +7610,6 @@
}
// =========================================================
- // THUMBNAILS
- // =========================================================
-
- public void reportThumbnail(IBinder token,
- Bitmap thumbnail, CharSequence description) {
- //System.out.println("Report thumbnail for " + token + ": " + thumbnail);
- final long origId = Binder.clearCallingIdentity();
- sendPendingThumbnail(null, token, thumbnail, description, true);
- Binder.restoreCallingIdentity(origId);
- }
-
- final void sendPendingThumbnail(ActivityRecord r, IBinder token,
- Bitmap thumbnail, CharSequence description, boolean always) {
- TaskRecord task;
- ArrayList<PendingThumbnailsRecord> receivers = null;
-
- //System.out.println("Send pending thumbnail: " + r);
-
- synchronized(this) {
- if (r == null) {
- r = ActivityRecord.isInStackLocked(token);
- if (r == null) {
- return;
- }
- }
- if (thumbnail == null && r.thumbHolder != null) {
- thumbnail = r.thumbHolder.lastThumbnail;
- description = r.thumbHolder.lastDescription;
- }
- if (thumbnail == null && !always) {
- // If there is no thumbnail, and this entry is not actually
- // going away, then abort for now and pick up the next
- // thumbnail we get.
- return;
- }
- task = r.task;
-
- int N = mPendingThumbnails.size();
- int i=0;
- while (i<N) {
- PendingThumbnailsRecord pr = mPendingThumbnails.get(i);
- //System.out.println("Looking in " + pr.pendingRecords);
- if (pr.pendingRecords.remove(r)) {
- if (receivers == null) {
- receivers = new ArrayList<PendingThumbnailsRecord>();
- }
- receivers.add(pr);
- if (pr.pendingRecords.size() == 0) {
- pr.finished = true;
- mPendingThumbnails.remove(i);
- N--;
- continue;
- }
- }
- i++;
- }
- }
-
- if (receivers != null) {
- final int N = receivers.size();
- for (int i=0; i<N; i++) {
- try {
- PendingThumbnailsRecord pr = receivers.get(i);
- pr.receiver.newThumbnail(
- task != null ? task.taskId : -1, thumbnail, description);
- if (pr.finished) {
- pr.receiver.finished();
- }
- } catch (Exception e) {
- Slog.w(TAG, "Exception thrown when sending thumbnail", e);
- }
- }
- }
- }
-
- // =========================================================
// CONTENT PROVIDERS
// =========================================================
@@ -15305,8 +15204,8 @@
// it when computing the final cached adj later. Note that we don't need to
// worry about this for max adj above, since max adj will always be used to
// keep it out of the cached vaues.
- adj = app.modifyRawOomAdj(adj);
-
+ app.curAdj = app.modifyRawOomAdj(adj);
+ app.curSchedGroup = schedGroup;
app.curProcState = procState;
app.foregroundActivities = foregroundActivities;
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 7a44473..7c3f288 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -23,6 +23,7 @@
import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
+import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ResultInfo;
import android.content.ComponentName;
@@ -131,7 +132,6 @@
boolean sleeping; // have we told the activity to sleep?
boolean waitingVisible; // true if waiting for a new act to become vis
boolean nowVisible; // is this activity's window visible?
- boolean thumbnailNeeded;// has someone requested a thumbnail?
boolean idle; // has the activity gone idle?
boolean hasBeenLaunched;// has this activity ever been launched?
boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
@@ -148,8 +148,7 @@
boolean mStartingWindowShown = false;
ActivityContainer mInitialActivityContainer;
- String activityLabel;
- Bitmap activityIcon;
+ ActivityManager.RecentsActivityValues activityValues; // the recents information for this activity
void dump(PrintWriter pw, String prefix) {
final long now = SystemClock.uptimeMillis();
@@ -239,7 +238,6 @@
pw.print(" immersive="); pw.print(immersive);
pw.print(" launchMode="); pw.println(launchMode);
pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
- pw.print(" thumbnailNeeded="); pw.print(thumbnailNeeded);
pw.print(" forceNewConfig="); pw.println(forceNewConfig);
pw.print(prefix); pw.print("mActivityType=");
pw.println(activityTypeToString(mActivityType));
@@ -375,7 +373,6 @@
visible = true;
waitingVisible = false;
nowVisible = false;
- thumbnailNeeded = false;
idle = false;
hasBeenLaunched = false;
mStackSupervisor = supervisor;
@@ -483,7 +480,7 @@
void setTask(TaskRecord newTask, ThumbnailHolder newThumbHolder, boolean isRoot) {
if (task != null && task.removeActivity(this)) {
if (task != newTask) {
- task.stack.removeTask(task);
+ task.stack.removeTask(task, false);
} else {
Slog.d(TAG, "!!! REMOVE THIS LOG !!! setTask: nearly removed stack=" +
(newTask == null ? null : newTask.stack));
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 6769c9c..ee39b67 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -53,7 +53,6 @@
import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.IActivityController;
-import android.app.IThumbnailReceiver;
import android.app.ResultInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.ComponentName;
@@ -73,7 +72,6 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.util.EventLog;
@@ -1098,6 +1096,36 @@
ensureActivitiesVisibleLocked(r, starting, null, configChanges, forceHomeShown);
}
+ // Checks if any of the stacks above this one has a fullscreen activity behind it.
+ // If so, this stack is hidden, otherwise it is visible.
+ private boolean isStackVisible() {
+ if (!isAttached()) {
+ return false;
+ }
+
+ if (mStackSupervisor.isFrontStack(this)) {
+ return true;
+ }
+
+ // Start at the task above this one and go up, looking for a visible
+ // fullscreen activity, or a translucent activity that requested the
+ // wallpaper to be shown behind it.
+ for (int i = mStacks.indexOf(this) + 1; i < mStacks.size(); i++) {
+ final ArrayList<TaskRecord> tasks = mStacks.get(i).getAllTasks();
+ for (int taskNdx = 0; taskNdx < tasks.size(); taskNdx++) {
+ final ArrayList<ActivityRecord> activities = tasks.get(taskNdx).mActivities;
+ for (int activityNdx = 0; activityNdx < activities.size(); activityNdx++) {
+ final ActivityRecord r = activities.get(activityNdx);
+ if (!r.finishing && r.visible && r.fullscreen) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
/**
* Make sure that all activities that need to be visible (that is, they
* currently can be seen by the user) actually are.
@@ -1122,8 +1150,8 @@
// make sure any activities under it are now visible.
boolean aboveTop = true;
boolean showHomeBehindStack = false;
- boolean behindFullscreen = !mStackSupervisor.isFrontStack(this) &&
- !(forceHomeShown && isHomeStack());
+ boolean behindFullscreen = !isStackVisible();
+
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
final ArrayList<ActivityRecord> activities = task.mActivities;
@@ -2537,13 +2565,6 @@
finishActivityResultsLocked(r, resultCode, resultData);
- if (!mService.mPendingThumbnails.isEmpty()) {
- // There are clients waiting to receive thumbnails so, in case
- // this is an activity that someone is waiting for, add it
- // to the pending list so we can correctly update the clients.
- mStackSupervisor.mCancelledThumbnails.add(r);
- }
-
if (mResumedActivity == r) {
boolean endTask = index <= 0;
if (DEBUG_VISBILITY || DEBUG_TRANSITION) Slog.v(TAG,
@@ -2782,13 +2803,6 @@
cleanUpActivityServicesLocked(r);
}
- if (!mService.mPendingThumbnails.isEmpty()) {
- // There are clients waiting to receive thumbnails so, in case
- // this is an activity that someone is waiting for, add it
- // to the pending list so we can correctly update the clients.
- mStackSupervisor.mCancelledThumbnails.add(r);
- }
-
// Get rid of any pending idle timeouts.
removeTimeoutsForActivityLocked(r);
}
@@ -2827,7 +2841,7 @@
if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.mOnTopOfHome) {
mStackSupervisor.moveHomeToTop();
}
- removeTask(task);
+ removeTask(task, false);
}
cleanUpActivityServicesLocked(r);
r.removeUriPermissionsLocked();
@@ -3535,9 +3549,7 @@
return didSomething;
}
- ActivityRecord getTasksLocked(IThumbnailReceiver receiver,
- PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
- ActivityRecord topRecord = null;
+ void getTasksLocked(List<RunningTaskInfo> list, int callingUid, boolean allowed) {
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
ActivityRecord r = null;
@@ -3548,6 +3560,9 @@
if (activities.isEmpty()) {
continue;
}
+ if (!allowed && !task.isHomeTask() && task.creatorUid != callingUid) {
+ continue;
+ }
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
r = activities.get(activityNdx);
@@ -3581,23 +3596,8 @@
ci.numRunning = numRunning;
//System.out.println(
// "#" + maxNum + ": " + " descr=" + ci.description);
- if (receiver != null) {
- if (localLOGV) Slog.v(
- TAG, "State=" + top.state + "Idle=" + top.idle
- + " app=" + top.app
- + " thr=" + (top.app != null ? top.app.thread : null));
- if (top.state == ActivityState.RESUMED || top.state == ActivityState.PAUSING) {
- if (top.idle && top.app != null && top.app.thread != null) {
- topRecord = top;
- } else {
- top.thumbnailNeeded = true;
- }
- }
- pending.pendingRecords.add(top);
- }
list.add(ci);
}
- return topRecord;
}
public void unhandledBackLocked() {
@@ -3717,7 +3717,7 @@
return starting;
}
- void removeTask(TaskRecord task) {
+ void removeTask(TaskRecord task, boolean moving) {
mStackSupervisor.endLockTaskModeIfTaskEnding(task);
mWindowManager.removeTask(task.taskId);
final ActivityRecord r = mResumedActivity;
@@ -3731,9 +3731,13 @@
mTaskHistory.get(taskNdx + 1).mOnTopOfHome = true;
}
mTaskHistory.remove(task);
- if (task.voiceInteractor != null) {
+ if (!moving && task.voiceSession != null) {
// This task was a voice interaction, so it should not remain on the
// recent tasks list.
+ try {
+ task.voiceSession.taskFinished(task.intent, task.taskId);
+ } catch (RemoteException e) {
+ }
mService.mRecentTasks.remove(task);
}
@@ -3753,7 +3757,7 @@
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
boolean toTop) {
TaskRecord task = new TaskRecord(taskId, info, intent, voiceSession, voiceInteractor);
- addTask(task, toTop);
+ addTask(task, toTop, false);
return task;
}
@@ -3761,13 +3765,19 @@
return new ArrayList<TaskRecord>(mTaskHistory);
}
- void addTask(final TaskRecord task, final boolean toTop) {
+ void addTask(final TaskRecord task, final boolean toTop, boolean moving) {
task.stack = this;
if (toTop) {
insertTaskAtTop(task);
} else {
mTaskHistory.add(0, task);
}
+ if (!moving && task.voiceSession != null) {
+ try {
+ task.voiceSession.taskStarted(task.intent, task.taskId);
+ } catch (RemoteException e) {
+ }
+ }
}
public int getStackId() {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 3770a07..2e979d2 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -41,7 +41,6 @@
import android.app.IActivityContainerCallback;
import android.app.IActivityManager;
import android.app.IApplicationThread;
-import android.app.IThumbnailReceiver;
import android.app.PendingIntent;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.IActivityManager.WaitResult;
@@ -191,10 +190,6 @@
/** List of activities that are in the process of going to sleep. */
final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<ActivityRecord>();
- /** List of ActivityRecord objects that have been finished and must still report back to a
- * pending thumbnail receiver. */
- final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
-
/** Used on user changes */
final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>();
@@ -591,10 +586,7 @@
return null;
}
- ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
- PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
- ActivityRecord r = null;
-
+ void getTasksLocked(int maxNum, List<RunningTaskInfo> list, int callingUid, boolean allowed) {
// Gather all of the running tasks for each stack into runningTaskLists.
ArrayList<ArrayList<RunningTaskInfo>> runningTaskLists =
new ArrayList<ArrayList<RunningTaskInfo>>();
@@ -605,10 +597,7 @@
final ActivityStack stack = stacks.get(stackNdx);
ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<RunningTaskInfo>();
runningTaskLists.add(stackTaskList);
- final ActivityRecord ar = stack.getTasksLocked(receiver, pending, stackTaskList);
- if (r == null && isFrontStack(stack)) {
- r = ar;
- }
+ stack.getTasksLocked(stackTaskList, callingUid, allowed);
}
}
@@ -635,8 +624,6 @@
break;
}
}
-
- return r;
}
ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
@@ -1912,7 +1899,6 @@
ArrayList<UserStartedState> startingUsers = null;
int NS = 0;
int NF = 0;
- IApplicationThread sendThumbnail = null;
boolean booting = false;
boolean enableScreen = false;
boolean activityRemoved = false;
@@ -1940,11 +1926,6 @@
// us, we can now deliver.
r.idle = true;
- if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
- sendThumbnail = r.app.thread;
- r.thumbnailNeeded = false;
- }
-
//Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
if (!mService.mBooted && isFrontStack(r.task.stack)) {
mService.mBooted = true;
@@ -1976,15 +1957,6 @@
mFinishingActivities.clear();
}
- final ArrayList<ActivityRecord> thumbnails;
- final int NT = mCancelledThumbnails.size();
- if (NT > 0) {
- thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
- mCancelledThumbnails.clear();
- } else {
- thumbnails = null;
- }
-
if (isFrontStack(mHomeStack)) {
booting = mService.mBooting;
mService.mBooting = false;
@@ -1995,28 +1967,6 @@
mStartingUsers.clear();
}
- // Perform the following actions from unsynchronized state.
- final IApplicationThread thumbnailThread = sendThumbnail;
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (thumbnailThread != null) {
- try {
- thumbnailThread.requestThumbnail(token);
- } catch (Exception e) {
- Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
- mService.sendPendingThumbnail(null, token, null, null, true);
- }
- }
-
- // Report back to any thumbnail receivers.
- for (int i = 0; i < NT; i++) {
- ActivityRecord r = thumbnails.get(i);
- mService.sendPendingThumbnail(r, null, null, null, true);
- }
- }
- });
-
// Stop any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (int i = 0; i < NS; i++) {
@@ -2287,8 +2237,8 @@
Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
return;
}
- task.stack.removeTask(task);
- stack.addTask(task, toTop);
+ task.stack.removeTask(task, true);
+ stack.addTask(task, toTop, true);
mWindowManager.addTask(taskId, stackId, toTop);
resumeTopActivitiesLocked();
}
@@ -3169,7 +3119,7 @@
}
}
ActivityInfo aInfo = resolveActivity(intent, resolvedType, 0, null, null, userId);
- if ((aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
+ if (aInfo != null && (aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
throw new SecurityException(
"Attempt to embed activity that has not set allowEmbedded=\"true\"");
}
@@ -3288,9 +3238,9 @@
} else {
mContainerState = CONTAINER_STATE_NO_SURFACE;
((VirtualActivityDisplay) mActivityDisplay).setSurface(null);
-// if (mStack.mPausingActivity == null && mStack.mResumedActivity != null) {
-// mStack.startPausingLocked(false, true);
-// }
+ if (mStack.mPausingActivity == null && mStack.mResumedActivity != null) {
+ mStack.startPausingLocked(false, true);
+ }
}
setSurfaceIfReady();
@@ -3300,6 +3250,11 @@
}
@Override
+ boolean isAttached() {
+ return mSurface != null && super.isAttached();
+ }
+
+ @Override
void setDrawn() {
synchronized (mService) {
mDrawn = true;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 83e8a4b..dd12a65 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -230,10 +230,10 @@
}
}
- public void noteScreenOn() {
+ public void noteScreenState(int state) {
enforceCallingPermission();
synchronized (mStats) {
- mStats.noteScreenOnLocked();
+ mStats.noteScreenStateLocked(state);
}
}
@@ -244,24 +244,19 @@
}
}
- public void noteScreenOff() {
- enforceCallingPermission();
- synchronized (mStats) {
- mStats.noteScreenOffLocked();
- }
- }
-
- public void noteInputEvent() {
- enforceCallingPermission();
- mStats.noteInputEventAtomic();
- }
-
public void noteUserActivity(int uid, int event) {
enforceCallingPermission();
synchronized (mStats) {
mStats.noteUserActivityLocked(uid, event);
}
}
+
+ public void noteInteractive(boolean interactive) {
+ enforceCallingPermission();
+ synchronized (mStats) {
+ mStats.noteInteractiveLocked(interactive);
+ }
+ }
public void noteMobileRadioPowerState(int powerState, long timestampNs) {
enforceCallingPermission();
diff --git a/services/core/java/com/android/server/am/PendingThumbnailsRecord.java b/services/core/java/com/android/server/am/PendingThumbnailsRecord.java
deleted file mode 100644
index e4eb4d0..0000000
--- a/services/core/java/com/android/server/am/PendingThumbnailsRecord.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2006 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.am;
-
-import android.app.IThumbnailReceiver;
-
-import java.util.HashSet;
-
-/**
- * This class keeps track of calls to getTasks() that are still
- * waiting for thumbnail images.
- */
-final class PendingThumbnailsRecord
-{
- final IThumbnailReceiver receiver; // who is waiting.
- final HashSet<ActivityRecord> pendingRecords; // HistoryRecord objects we still wait for.
- boolean finished; // Is pendingRecords empty?
-
- PendingThumbnailsRecord(IThumbnailReceiver _receiver)
- {
- receiver = _receiver;
- pendingRecords = new HashSet<ActivityRecord>();
- finished = false;
- }
-}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 68da54d..9f0bc10 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -52,9 +52,15 @@
String stringName; // caching of toString() result.
int userId; // user for which this task was created
+ int creatorUid; // The app uid that originally created the task
int numFullscreen; // Number of fullscreen activities.
+ // This represents the last resolved activity values for this task
+ // NOTE: This value needs to be persisted with each task
+ ActivityManager.RecentsActivityValues lastActivityValues =
+ new ActivityManager.RecentsActivityValues();
+
/** List of all activities in the task arranged in history order */
final ArrayList<ActivityRecord> mActivities = new ArrayList<ActivityRecord>();
@@ -131,9 +137,8 @@
rootWasReset = true;
}
- if (info.applicationInfo != null) {
- userId = UserHandle.getUserId(info.applicationInfo.uid);
- }
+ userId = UserHandle.getUserId(info.applicationInfo.uid);
+ creatorUid = info.applicationInfo.uid;
}
void disposeThumbnail() {
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 026fd296..1b40cdf 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -411,6 +411,7 @@
if (!factoryTest) {
intentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
context.registerReceiver(mBootCompletedReceiver, intentFilter);
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 1f38eb6..3ae0fd5 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -393,11 +393,7 @@
// Initialize screen state for battery stats.
try {
- if (mPowerState.getScreenState() != Display.STATE_OFF) {
- mBatteryStats.noteScreenOn();
- } else {
- mBatteryStats.noteScreenOff();
- }
+ mBatteryStats.noteScreenState(mPowerState.getScreenState());
mBatteryStats.noteScreenBrightness(mPowerState.getScreenBrightness());
} catch (RemoteException ex) {
// same process
@@ -641,11 +637,7 @@
if (mPowerState.getScreenState() != state) {
mPowerState.setScreenState(state);
try {
- if (state != Display.STATE_OFF) {
- mBatteryStats.noteScreenOn();
- } else {
- mBatteryStats.noteScreenOff();
- }
+ mBatteryStats.noteScreenState(state);
} catch (RemoteException ex) {
// same process
}
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 91afec7..7f43e43 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -21,6 +21,7 @@
import android.os.IBinder;
import android.os.Looper;
import android.os.SystemProperties;
+import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayEventReceiver;
@@ -47,8 +48,6 @@
new SparseArray<LocalDisplayDevice>();
private HotplugDisplayEventReceiver mHotplugReceiver;
- private final SurfaceControl.PhysicalDisplayInfo mTempPhys = new SurfaceControl.PhysicalDisplayInfo();
-
// Called with SyncRoot lock held.
public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
Context context, Handler handler, Listener listener) {
@@ -68,14 +67,31 @@
private void tryConnectDisplayLocked(int builtInDisplayId) {
IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
- if (displayToken != null && SurfaceControl.getDisplayInfo(displayToken, mTempPhys)) {
+ if (displayToken != null) {
+ SurfaceControl.PhysicalDisplayInfo[] configs =
+ SurfaceControl.getDisplayConfigs(displayToken);
+ if (configs == null) {
+ // There are no valid configs for this device, so we can't use it
+ Slog.w(TAG, "No valid configs found for display device " +
+ builtInDisplayId);
+ return;
+ }
+ int activeConfig = SurfaceControl.getActiveConfig(displayToken);
+ if (activeConfig < 0) {
+ // There is no active config, and for now we don't have the
+ // policy to set one.
+ Slog.w(TAG, "No active config found for display device " +
+ builtInDisplayId);
+ return;
+ }
LocalDisplayDevice device = mDevices.get(builtInDisplayId);
if (device == null) {
// Display was added.
- device = new LocalDisplayDevice(displayToken, builtInDisplayId, mTempPhys);
+ device = new LocalDisplayDevice(displayToken, builtInDisplayId,
+ configs[activeConfig]);
mDevices.put(builtInDisplayId, device);
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
- } else if (device.updatePhysicalDisplayInfoLocked(mTempPhys)) {
+ } else if (device.updatePhysicalDisplayInfoLocked(configs[activeConfig])) {
// Display properties changed.
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
}
@@ -228,4 +244,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index a165f26..14ef5a9 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -146,9 +146,7 @@
@Override
public void performTraversalInTransactionLocked() {
- if (mSurface != null) {
- setSurfaceInTransactionLocked(mSurface);
- }
+ setSurfaceInTransactionLocked(mSurface);
}
public void setSurfaceLocked(Surface surface) {
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index fd2f8a1..8968da3 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -642,8 +642,9 @@
try {
synchronized (mMcuHal) {
if (mReleased) {
- throw new IllegalStateException("This operation cannot be performed "
- + "because the dream has ended.");
+ Slog.w(TAG, "Ignoring message to MCU HAL because the dream "
+ + "has already ended: " + msg);
+ return null;
}
return mMcuHal.sendMessage(msg, arg);
}
diff --git a/services/core/java/com/android/server/hdmi/FeatureAction.java b/services/core/java/com/android/server/hdmi/FeatureAction.java
new file mode 100644
index 0000000..296cc5b
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/FeatureAction.java
@@ -0,0 +1,211 @@
+/*
+ * 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;
+import android.hardware.hdmi.HdmiCecMessage;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Encapsulates a sequence of CEC/MHL command exchange for a certain feature.
+ *
+ * <p>Many CEC/MHL features are accomplished by CEC devices on the bus exchanging
+ * more than one command. {@link FeatureAction} represents the life cycle of the communication,
+ * manages the state as the process progresses, and if necessary, returns the result
+ * to the caller which initiates the action, through the callback given at the creation
+ * of the object. All the actual action classes inherit FeatureAction.
+ *
+ * <p>More than one FeatureAction objects can be up and running simultaneously,
+ * maintained by {@link HdmiControlService}. Each action is passed a new command
+ * arriving from the bus, and either consumes it if the command is what the action expects,
+ * or yields it to other action.
+ *
+ * Declared as package private, accessed by {@link HdmiControlService} only.
+ */
+abstract class FeatureAction {
+
+ private static final String TAG = "FeatureAction";
+
+ // Timer handler message used for timeout event
+ protected static final int MSG_TIMEOUT = 100;
+
+ // Default timeout for the incoming command to arrive in response to a request
+ protected static final int TIMEOUT_MS = 1000;
+
+ // Default state used in common by all the feature actions.
+ protected static final int STATE_NONE = 0;
+
+ // Internal state indicating the progress of action.
+ protected int mState = STATE_NONE;
+
+ protected final HdmiControlService mService;
+
+ // Logical address of the device for which the feature action is taken. The commands
+ // generated in an action all use this field as source address.
+ protected final int mSourceAddress;
+
+ // Timer that manages timeout events.
+ protected ActionTimer mActionTimer;
+
+ FeatureAction(HdmiControlService service, int sourceAddress) {
+ mService = service;
+ mSourceAddress = sourceAddress;
+ mActionTimer = createActionTimer(service.getServiceLooper());
+ }
+
+ @VisibleForTesting
+ void setActionTimer(ActionTimer actionTimer) {
+ mActionTimer = actionTimer;
+ }
+
+ /**
+ * Called right after the action is created. Initialization or first step to take
+ * for the action can be done in this method.
+ *
+ * @return true if the operation is successful; otherwise false.
+ */
+ abstract boolean start();
+
+ /**
+ * Process the command. Called whenever a new command arrives.
+ *
+ * @param cmd command to process
+ * @return true if the command was consumed in the process; Otherwise false, which
+ * indicates that the command shall be handled by other actions.
+ */
+ abstract boolean processCommand(HdmiCecMessage cmd);
+
+ /**
+ * Called when the action should handle the timer event it created before.
+ *
+ * <p>CEC standard mandates each command transmission should be responded within
+ * certain period of time. The method is called when the timer it created as it transmitted
+ * a command gets expired. Inner logic should take an appropriate action.
+ *
+ * @param state the state associated with the time when the timer was created
+ */
+ abstract void handleTimerEvent(int state);
+
+ /**
+ * Timer handler interface used for FeatureAction classes.
+ */
+ interface ActionTimer {
+ /**
+ * Send a timer message.
+ *
+ * Also carries the state of the action when the timer is created. Later this state is
+ * compared to the one the action is in when it receives the timer to let the action tell
+ * the right timer to handle.
+ *
+ * @param state state of the action is in
+ * @param delayMillis amount of delay for the timer
+ */
+ void sendTimerMessage(int state, long delayMillis);
+ }
+
+ private class ActionTimerHandler extends Handler implements ActionTimer {
+
+ public ActionTimerHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void sendTimerMessage(int state, long delayMillis) {
+ sendMessageDelayed(obtainMessage(MSG_TIMEOUT, state), delayMillis);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_TIMEOUT:
+ handleTimerEvent(msg.arg1);
+ break;
+ default:
+ Slog.w(TAG, "Unsupported message:" + msg.what);
+ break;
+ }
+ }
+ }
+
+ private ActionTimer createActionTimer(Looper looper) {
+ return new ActionTimerHandler(looper);
+ }
+
+ // Add a new timer. The timer event will come to mActionTimer.handleMessage() in
+ // delayMillis.
+ protected void addTimer(int state, int delayMillis) {
+ mActionTimer.sendTimerMessage(state, delayMillis);
+ }
+
+ static HdmiCecMessage buildCommand(int src, int dst, int opcode, byte[] params) {
+ return new HdmiCecMessage(src, dst, opcode, params);
+ }
+
+ // Build a CEC command that does not have parameter.
+ static HdmiCecMessage buildCommand(int src, int dst, int opcode) {
+ return new HdmiCecMessage(src, dst, opcode, HdmiCecMessage.EMPTY_PARAM);
+ }
+
+ protected final void sendCommand(HdmiCecMessage cmd) {
+ mService.sendCecCommand(cmd);
+ }
+
+ protected final void sendBroadcastCommand(int opcode, byte[] param) {
+ sendCommand(buildCommand(mSourceAddress, HdmiCec.ADDR_BROADCAST, opcode, param));
+ }
+
+ /**
+ * Finish up the action. Reset the state, and remove itself from the action queue.
+ */
+ protected void finish() {
+ mState = STATE_NONE;
+ removeAction(this);
+ }
+
+ /**
+ * Remove the action from the action queue. This is called after the action finishes
+ * its role.
+ *
+ * @param action
+ */
+ private void removeAction(FeatureAction action) {
+ mService.removeAction(action);
+ }
+
+ // Utility methods for generating parameter byte arrays for CEC commands.
+ protected static byte[] uiCommandParam(int uiCommand) {
+ return new byte[] {(byte) uiCommand};
+ }
+
+ protected static byte[] physicalAddressParam(int physicalAddress) {
+ return new byte[] {
+ (byte) ((physicalAddress >> 8) & 0xFF),
+ (byte) (physicalAddress & 0xFF)
+ };
+ }
+
+ protected static byte[] pathPairParam(int oldPath, int newPath) {
+ return new byte[] {
+ (byte) ((oldPath >> 8) & 0xFF), (byte) (oldPath & 0xFF),
+ (byte) ((newPath >> 8) & 0xFF), (byte) (newPath & 0xFF)
+ };
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index c87fc99..b103a4d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -40,7 +40,7 @@
*
* <p>Declared as package-private, accessed by {@link HdmiControlService} only.
*/
-class HdmiCecController {
+final class HdmiCecController {
private static final String TAG = "HdmiCecController";
private static final byte[] EMPTY_BODY = EmptyArray.BYTE;
@@ -313,6 +313,63 @@
return mDeviceInfos.get(logicalAddress);
}
+ /**
+ * Add a new logical address to the device. Device's HW should be notified
+ * when a new logical address is assigned to a device, so that it can accept
+ * a command having available destinations.
+ *
+ * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+ *
+ * @param newLogicalAddress a logical address to be added
+ * @return 0 on success. Otherwise, returns negative value
+ */
+ int addLogicalAddress(int newLogicalAddress) {
+ if (HdmiCec.isValidAddress(newLogicalAddress)) {
+ return nativeAddLogicalAddress(mNativePtr, newLogicalAddress);
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * Clear all logical addresses registered in the device.
+ *
+ * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+ */
+ void clearLogicalAddress() {
+ nativeClearLogicalAddress(mNativePtr);
+ }
+
+ /**
+ * Return the physical address of the device.
+ *
+ * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+ *
+ * @return CEC physical address of the device. The range of success address
+ * is between 0x0000 and 0xFFFF. If failed it returns -1
+ */
+ int getPhysicalAddress() {
+ return nativeGetPhysicalAddress(mNativePtr);
+ }
+
+ /**
+ * Return CEC version of the device.
+ *
+ * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+ */
+ int getVersion() {
+ return nativeGetVersion(mNativePtr);
+ }
+
+ /**
+ * Return vendor id of the device.
+ *
+ * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+ */
+ int getVendorId() {
+ return nativeGetVendorId(mNativePtr);
+ }
+
private void init(HdmiControlService service, long nativePtr) {
mIoHandler = new IoHandler(service.getServiceLooper());
mControlHandler = new ControlHandler(service.getServiceLooper());
@@ -364,6 +421,11 @@
}
private static native long nativeInit(HdmiCecController handler);
- private static native int nativeSendCecCommand(long contollerPtr, int srcAddress,
+ private static native int nativeSendCecCommand(long controllerPtr, int srcAddress,
int dstAddress, byte[] body);
+ private static native int nativeAddLogicalAddress(long controllerPtr, int logicalAddress);
+ private static native void nativeClearLogicalAddress(long controllerPtr);
+ private static native int nativeGetPhysicalAddress(long controllerPtr);
+ private static native int nativeGetVersion(long controllerPtr);
+ private static native int nativeGetVendorId(long controllerPtr);
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 7c1995e..f99c717 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -18,6 +18,8 @@
import android.annotation.Nullable;
import android.content.Context;
+import android.hardware.hdmi.HdmiCecDeviceInfo;
+import android.hardware.hdmi.HdmiCecMessage;
import android.os.HandlerThread;
import android.os.Looper;
import android.util.Slog;
@@ -77,4 +79,41 @@
Looper getServiceLooper() {
return Looper.myLooper();
}
+
+ /**
+ * Add a new {@link FeatureAction} to the action queue.
+ *
+ * @param action {@link FeatureAction} to add
+ */
+ void addAction(FeatureAction action) {
+ // TODO: Implement this.
+ }
+
+
+ /**
+ * Remove the given {@link FeatureAction} object from the action queue.
+ *
+ * @param action {@link FeatureAction} to add
+ */
+ void removeAction(FeatureAction action) {
+ // TODO: Implement this.
+ }
+
+ /**
+ * Transmit a CEC command to CEC bus.
+ *
+ * @param command CEC command to send out
+ */
+ void sendCecCommand(HdmiCecMessage command) {
+ // TODO: Implement this.
+ }
+
+ /**
+ * Add a new {@link HdmiCecDeviceInfo} to controller.
+ *
+ * @param deviceInfo new device information object to add
+ */
+ void addDeviceInfo(HdmiCecDeviceInfo deviceInfo) {
+ // TODO: Implement this.
+ }
}
diff --git a/services/core/java/com/android/server/hdmi/NewDeviceAction.java b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
new file mode 100644
index 0000000..c84a067
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
@@ -0,0 +1,165 @@
+/*
+ * 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;
+import android.hardware.hdmi.HdmiCecDeviceInfo;
+import android.hardware.hdmi.HdmiCecMessage;
+import android.util.Slog;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Feature action that discovers the information of a newly found logical device.
+ *
+ * This action is created when receiving <Report Physical Address>, a CEC command a newly
+ * connected HDMI-CEC device broadcasts to announce its advent. Additional commands are issued in
+ * this action to gather more information on the device such as OSD name and device vendor ID.
+ *
+ * <p>The result is made in the form of {@link HdmiCecDeviceInfo} object, and passed to service
+ * for the management through its life cycle.
+ *
+ * <p>Package-private, accessed by {@link HdmiControlService} only.
+ */
+final class NewDeviceAction extends FeatureAction {
+
+ private static final String TAG = "NewDeviceAction";
+
+ // State in which the action sent <Give OSD Name> and is waiting for <Set OSD Name>
+ // that contains the name of the device for display on screen.
+ static final int STATE_WAITING_FOR_SET_OSD_NAME = 1;
+
+ // State in which the action sent <Give Device Vendor ID> and is waiting for
+ // <Device Vendor ID> that contains the vendor ID of the device.
+ static final int STATE_WAITING_FOR_DEVICE_VENDOR_ID = 2;
+
+ private final int mDeviceLogicalAddress;
+ private final int mDevicePhysicalAddress;
+
+ private int mVendorId;
+ private String mDisplayName;
+
+ /**
+ * Constructor.
+ *
+ * @param service {@link HdmiControlService} instance
+ * @param sourceAddress logical address to be used as source address
+ * @param deviceLogicalAddress logical address of the device in interest
+ * @param devicePhysicalAddress physical address of the device in interest
+ */
+ NewDeviceAction(HdmiControlService service, int sourceAddress, int deviceLogicalAddress,
+ int devicePhysicalAddress) {
+ super(service, sourceAddress);
+ mDeviceLogicalAddress = deviceLogicalAddress;
+ mDevicePhysicalAddress = devicePhysicalAddress;
+ mVendorId = HdmiCec.UNKNOWN_VENDOR_ID;
+ }
+
+ @Override
+ public boolean start() {
+ sendCommand(
+ buildCommand(mSourceAddress, mDeviceLogicalAddress, HdmiCec.MESSAGE_GET_OSD_NAME));
+ mState = STATE_WAITING_FOR_SET_OSD_NAME;
+ addTimer(mState, TIMEOUT_MS);
+ return true;
+ }
+
+ @Override
+ public boolean processCommand(HdmiCecMessage cmd) {
+ // For the logical device in interest, we want two more pieces of information -
+ // osd name and vendor id. They are requested in sequence. In case we don't
+ // get the expected responses (either by timeout or by receiving <feature abort> command),
+ // set them to a default osd name and unknown vendor id respectively.
+ int opcode = cmd.getOpcode();
+ int src = cmd.getSource();
+ byte[] params = cmd.getParams();
+
+ if (mDeviceLogicalAddress != src) {
+ return false;
+ }
+
+ if (mState == STATE_WAITING_FOR_SET_OSD_NAME) {
+ if (opcode == HdmiCec.MESSAGE_SET_OSD_NAME) {
+ try {
+ mDisplayName = new String(params, "US-ASCII");
+ } catch (UnsupportedEncodingException e) {
+ Slog.e(TAG, "Failed to get OSD name: " + e.getMessage());
+ }
+ mState = STATE_WAITING_FOR_DEVICE_VENDOR_ID;
+ requestVendorId();
+ return true;
+ } else if (opcode == HdmiCec.MESSAGE_FEATURE_ABORT) {
+ int requestOpcode = params[1];
+ if (requestOpcode == HdmiCec.MESSAGE_SET_OSD_NAME) {
+ mState = STATE_WAITING_FOR_DEVICE_VENDOR_ID;
+ requestVendorId();
+ return true;
+ }
+ }
+ } else if (mState == STATE_WAITING_FOR_DEVICE_VENDOR_ID) {
+ if (opcode == HdmiCec.MESSAGE_DEVICE_VENDOR_ID) {
+ if (params.length == 3) {
+ mVendorId = (params[0] << 16) + (params[1] << 8) + params[2];
+ } else {
+ Slog.e(TAG, "Failed to get device vendor ID: ");
+ }
+ addDeviceInfo();
+ finish();
+ return true;
+ } else if (opcode == HdmiCec.MESSAGE_FEATURE_ABORT) {
+ int requestOpcode = params[1];
+ if (requestOpcode == HdmiCec.MESSAGE_DEVICE_VENDOR_ID) {
+ addDeviceInfo();
+ finish();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private void requestVendorId() {
+ sendCommand(buildCommand(mSourceAddress, mDeviceLogicalAddress,
+ HdmiCec.MESSAGE_GIVE_DEVICE_VENDOR_ID));
+ addTimer(mState, TIMEOUT_MS);
+ }
+
+ private void addDeviceInfo() {
+ if (mDisplayName == null) {
+ mDisplayName = HdmiCec.getDefaultDeviceName(mDeviceLogicalAddress);
+ }
+ mService.addDeviceInfo(new HdmiCecDeviceInfo(
+ mDeviceLogicalAddress, mDevicePhysicalAddress,
+ HdmiCec.getTypeFromAddress(mDeviceLogicalAddress),
+ mVendorId, mDisplayName));
+ }
+
+ @Override
+ public void handleTimerEvent(int state) {
+ if (mState == STATE_NONE || mState != state) {
+ return;
+ }
+ if (state == STATE_WAITING_FOR_SET_OSD_NAME) {
+ // Osd name request timed out. Try vendor id
+ mState = STATE_WAITING_FOR_DEVICE_VENDOR_ID;
+ requestVendorId();
+ } else if (state == STATE_WAITING_FOR_DEVICE_VENDOR_ID) {
+ // vendor id timed out. Go ahead creating the device info what we've got so far.
+ addDeviceInfo();
+ finish();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index ab2a723..3dc17fc 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -238,6 +238,8 @@
pw.println(indent + "transport controls enabled=" + mTransportPerformerEnabled);
pw.println(indent + "rating type=" + mRatingType);
pw.println(indent + "controllers: " + mControllerCallbacks.size());
+ pw.println(indent + "state=" + mPlaybackState.toString());
+ pw.println(indent + "metadata:" + getShortMetadataString());
pw.println(indent + "route requests {");
int size = mRequests.size();
for (int i = 0; i < size; i++) {
@@ -249,6 +251,13 @@
pw.println(indent + "params=" + (mRequest == null ? null : mRequest.toString()));
}
+ private String getShortMetadataString() {
+ int fields = mMetadata == null ? 0 : mMetadata.size();
+ String title = mMetadata == null ? null : mMetadata
+ .getString(MediaMetadata.METADATA_KEY_TITLE);
+ return "size=" + fields + ", title=" + title;
+ }
+
private void onDestroy() {
mService.destroySession(this);
}
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index ce4c1ed..b41b478 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -21,8 +21,7 @@
public interface NotificationDelegate {
void onSetDisabled(int status);
void onClearAll(int callingUid, int callingPid, int userId);
- void onNotificationClick(int callingUid, int callingPid,
- String pkg, String tag, int id, int userId);
+ void onNotificationClick(int callingUid, int callingPid, String key);
void onNotificationClear(int callingUid, int callingPid,
String pkg, String tag, int id, int userId);
void onNotificationError(int callingUid, int callingPid,
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 2e52983..7aa5d79 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -602,10 +602,20 @@
}
@Override
- public void onNotificationClick(int callingUid, int callingPid,
- String pkg, String tag, int id, int userId) {
- cancelNotification(callingUid, callingPid, pkg, tag, id, Notification.FLAG_AUTO_CANCEL,
- Notification.FLAG_FOREGROUND_SERVICE, false, userId, REASON_DELEGATE_CLICK, null);
+ public void onNotificationClick(int callingUid, int callingPid, String key) {
+ synchronized (mNotificationList) {
+ EventLogTags.writeNotificationClicked(key);
+ NotificationRecord r = mNotificationsByKey.get(key);
+ if (r == null) {
+ Log.w(TAG, "No notification with key: " + key);
+ return;
+ }
+ StatusBarNotification sbn = r.sbn;
+ cancelNotification(callingUid, callingPid, sbn.getPackageName(), sbn.getTag(),
+ sbn.getId(), Notification.FLAG_AUTO_CANCEL,
+ Notification.FLAG_FOREGROUND_SERVICE, false, r.getUserId(),
+ REASON_DELEGATE_CLICK, null);
+ }
}
@Override
@@ -1612,7 +1622,8 @@
// Should this notification make noise, vibe, or use the LED?
final boolean canInterrupt = (score >= SCORE_INTERRUPTION_THRESHOLD) && !intercept;
- if (DBG) Slog.v(TAG, "canInterrupt=" + canInterrupt + " intercept=" + intercept);
+ if (DBG || intercept) Slog.v(TAG,
+ "pkg=" + pkg + " canInterrupt=" + canInterrupt + " intercept=" + intercept);
synchronized (mNotificationList) {
final StatusBarNotification n = new StatusBarNotification(
pkg, opPkg, id, tag, callingUid, callingPid, score, notification,
diff --git a/services/core/java/com/android/server/pm/ForwardingIntentFilter.java b/services/core/java/com/android/server/pm/ForwardingIntentFilter.java
index aba796b..85bde98 100644
--- a/services/core/java/com/android/server/pm/ForwardingIntentFilter.java
+++ b/services/core/java/com/android/server/pm/ForwardingIntentFilter.java
@@ -32,22 +32,29 @@
*/
class ForwardingIntentFilter extends IntentFilter {
private static final String ATTR_USER_ID_DEST = "userIdDest";
+ private static final String ATTR_REMOVABLE = "removable";
private static final String ATTR_FILTER = "filter";
private static final String TAG = "ForwardingIntentFilter";
// If the intent matches the IntentFilter, then it can be forwarded to this userId.
final int mUserIdDest;
+ boolean mRemovable;
- ForwardingIntentFilter(IntentFilter filter, int userIdDest) {
+ ForwardingIntentFilter(IntentFilter filter, boolean removable, int userIdDest) {
super(filter);
mUserIdDest = userIdDest;
+ mRemovable = removable;
}
public int getUserIdDest() {
return mUserIdDest;
}
+ public boolean isRemovable() {
+ return mRemovable;
+ }
+
ForwardingIntentFilter(XmlPullParser parser) throws XmlPullParserException, IOException {
String userIdDestString = parser.getAttributeValue(null, ATTR_USER_ID_DEST);
if (userIdDestString == null) {
@@ -58,6 +65,10 @@
} else {
mUserIdDest = Integer.parseInt(userIdDestString);
}
+ String removableString = parser.getAttributeValue(null, ATTR_REMOVABLE);
+ if (removableString != null) {
+ mRemovable = Boolean.parseBoolean(removableString);
+ }
int outerDepth = parser.getDepth();
String tagName = parser.getName();
int type;
@@ -89,6 +100,7 @@
public void writeToXml(XmlSerializer serializer) throws IOException {
serializer.attribute(null, ATTR_USER_ID_DEST, Integer.toString(mUserIdDest));
+ serializer.attribute(null, ATTR_REMOVABLE, Boolean.toString(mRemovable));
serializer.startTag(null, ATTR_FILTER);
super.writeToXml(serializer);
serializer.endTag(null, ATTR_FILTER);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a133d42..6a843a8 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11112,42 +11112,32 @@
}
}
- /*
- * For filters that are added with this method:
- * if an intent for the user whose id is userIdOrig matches the filter, then this intent can
- * also be resolved in the user whose id is userIdDest.
- */
@Override
- public void addForwardingIntentFilter(IntentFilter filter, int userIdOrig, int userIdDest) {
- int callingUid = Binder.getCallingUid();
- if (callingUid != Process.SYSTEM_UID) {
- throw new SecurityException(
- "addForwardingIntentFilter can only be run by the system");
- }
+ public void addForwardingIntentFilter(IntentFilter filter, boolean removable, int userIdOrig,
+ int userIdDest) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
if (filter.countActions() == 0) {
Slog.w(TAG, "Cannot set a forwarding intent filter with no filter actions");
return;
}
synchronized (mPackages) {
mSettings.editForwardingIntentResolverLPw(userIdOrig).addFilter(
- new ForwardingIntentFilter(filter, userIdDest));
+ new ForwardingIntentFilter(filter, removable, userIdDest));
mSettings.writePackageRestrictionsLPr(userIdOrig);
}
}
@Override
public void clearForwardingIntentFilters(int userIdOrig) {
- int callingUid = Binder.getCallingUid();
- if (callingUid != Process.SYSTEM_UID) {
- throw new SecurityException(
- "clearForwardingIntentFilter can only be run by the system");
- }
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
synchronized (mPackages) {
ForwardingIntentResolver fir = mSettings.editForwardingIntentResolverLPw(userIdOrig);
HashSet<ForwardingIntentFilter> set =
new HashSet<ForwardingIntentFilter>(fir.filterSet());
for (ForwardingIntentFilter fif : set) {
- fir.removeFilter(fif);
+ if (fif.isRemovable()) fir.removeFilter(fif);
}
mSettings.writePackageRestrictionsLPr(userIdOrig);
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 14df347..3239b46 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1092,6 +1092,9 @@
// on next startup, in case the runtime stops now before stopping and
// removing the user completely.
user.partial = true;
+ // Mark it as disabled, so that it isn't returned any more when
+ // profiles are queried.
+ user.flags |= UserInfo.FLAG_DISABLED;
writeUserLocked(user);
}
if (DBG) Slog.i(LOG_TAG, "Stopping user " + userHandle);
@@ -1120,6 +1123,7 @@
// wiping the user's system directory and removing from the user list
long ident = Binder.clearCallingIdentity();
try {
+ final boolean isManaged = getUserInfo(userHandle).isManagedProfile();
Intent addedIntent = new Intent(Intent.ACTION_USER_REMOVED);
addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userHandle);
mContext.sendOrderedBroadcastAsUser(addedIntent, UserHandle.ALL,
@@ -1140,6 +1144,11 @@
removeUserStateLocked(userHandle);
}
}
+ // Send broadcast to notify system that the user removed was a
+ // managed user.
+ if (isManaged) {
+ sendProfileRemovedBroadcast(userHandle);
+ }
}
}.start();
}
@@ -1191,6 +1200,13 @@
parent.delete();
}
+ private void sendProfileRemovedBroadcast(int userHandle) {
+ Intent managedProfileIntent = new Intent(Intent.ACTION_MANAGED_PROFILE_REMOVED);
+ managedProfileIntent.putExtra(Intent.EXTRA_USER, new UserHandle(userHandle));
+ // Note: This makes an assumption that the parent owner is user 0.
+ mContext.sendBroadcastAsUser(managedProfileIntent, UserHandle.OWNER, null);
+ }
+
@Override
public Bundle getApplicationRestrictions(String packageName) {
return getApplicationRestrictionsForUser(packageName, UserHandle.getCallingUserId());
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index d9e95c7..2d6cc7c 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -132,6 +132,11 @@
mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
mScreenOffIntent.addFlags(
Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+
+ // Initialize interactive state for battery stats.
+ try {
+ mBatteryStats.noteInteractive(true);
+ } catch (RemoteException ex) { }
}
/**
@@ -259,7 +264,14 @@
// Going to sleep...
mLastGoToSleepReason = reason;
}
- mInputManagerInternal.setInteractive(interactive);
+ }
+
+ mInputManagerInternal.setInteractive(interactive);
+
+ if (interactive) {
+ try {
+ mBatteryStats.noteInteractive(true);
+ } catch (RemoteException ex) { }
}
}
@@ -289,6 +301,12 @@
}
}
}
+
+ if (!interactive) {
+ try {
+ mBatteryStats.noteInteractive(false);
+ } catch (RemoteException ex) { }
+ }
}
/**
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index cfe24fe..6d2e8592 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -496,6 +496,7 @@
filter = new IntentFilter();
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiver(new BootCompletedReceiver(), filter, null, mHandler);
filter = new IntentFilter();
diff --git a/services/core/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java
index 486477a..5deb2b8 100644
--- a/services/core/java/com/android/server/search/SearchManagerService.java
+++ b/services/core/java/com/android/server/search/SearchManagerService.java
@@ -70,8 +70,9 @@
*/
public SearchManagerService(Context context) {
mContext = context;
- mContext.registerReceiver(new BootCompletedReceiver(),
- new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+ IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ mContext.registerReceiver(new BootCompletedReceiver(), filter);
mContext.registerReceiver(new UserReceiver(),
new IntentFilter(Intent.ACTION_USER_REMOVED));
new MyPackageMonitor().register(context, null, UserHandle.ALL, true);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 91f796b..022bdae 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -546,13 +546,13 @@
}
@Override
- public void onNotificationClick(String pkg, String tag, int id, int userId) {
+ public void onNotificationClick(String key) {
enforceStatusBarService();
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
long identity = Binder.clearCallingIdentity();
try {
- mNotificationDelegate.onNotificationClick(callingUid, callingPid, pkg, tag, id, userId);
+ mNotificationDelegate.onNotificationClick(callingUid, callingPid, key);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
index 527216d..27c8876 100644
--- a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
+++ b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
@@ -43,6 +43,16 @@
// Send message to other device. Note that it runs in IO thread.
int sendMessage(const cec_message_t& message);
+ // Add a logical address to device.
+ int addLogicalAddress(cec_logical_address_t address);
+ // Clear all logical address registered to the device.
+ void clearLogicaladdress();
+ // Get physical address of device.
+ int getPhysicalAddress();
+ // Get CEC version from driver.
+ int getVersion();
+ // Get vendor id used for vendor command.
+ uint32_t getVendorId();
private:
// Propagate the message up to Java layer.
@@ -94,6 +104,34 @@
return mDevice->send_message(mDevice, &message);
}
+int HdmiCecController::addLogicalAddress(cec_logical_address_t address) {
+ return mDevice->add_logical_address(mDevice, address);
+}
+
+void HdmiCecController::clearLogicaladdress() {
+ mDevice->clear_logical_address(mDevice);
+}
+
+int HdmiCecController::getPhysicalAddress() {
+ uint16_t physicalAddress = 0xFFFF;
+ if (mDevice->get_physical_address(mDevice, &physicalAddress) == 0) {
+ return physicalAddress;
+ }
+ return -1;
+}
+
+int HdmiCecController::getVersion() {
+ int version = 0;
+ mDevice->get_version(mDevice, &version);
+ return version;
+}
+
+uint32_t HdmiCecController::getVendorId() {
+ uint32_t vendorId = 0;
+ mDevice->get_vendor_id(mDevice, &vendorId);
+ return vendorId;
+}
+
// static
void HdmiCecController::checkAndClearExceptionFromCallback(JNIEnv* env,
const char* methodName) {
@@ -180,12 +218,51 @@
return controller->sendMessage(message);
}
+static jint nativeAddLogicalAddress(JNIEnv* env, jclass clazz,
+ jlong controllerPtr, jint logicalAddress) {
+ HdmiCecController* controller =
+ reinterpret_cast<HdmiCecController*>(controllerPtr);
+ return controller->addLogicalAddress(
+ static_cast<cec_logical_address_t>(logicalAddress));
+}
+
+static void nativeClearLogicalAddress(JNIEnv* env, jclass clazz,
+ jlong controllerPtr) {
+ HdmiCecController* controller =
+ reinterpret_cast<HdmiCecController*>(controllerPtr);
+ controller->clearLogicaladdress();
+}
+
+static jint nativeGetPhysicalAddress(JNIEnv* env, jclass clazz,
+ jlong controllerPtr) {
+ HdmiCecController* controller =
+ reinterpret_cast<HdmiCecController*>(controllerPtr);
+ return controller->getPhysicalAddress();
+}
+
+static jint nativeGetVersion(JNIEnv* env, jclass clazz,
+ jlong controllerPtr) {
+ HdmiCecController* controller =
+ reinterpret_cast<HdmiCecController*>(controllerPtr);
+ return controller->getVersion();
+}
+
+static jint nativeGetVendorId(JNIEnv* env, jclass clazz, jlong controllerPtr) {
+ HdmiCecController* controller =
+ reinterpret_cast<HdmiCecController*>(controllerPtr);
+ return controller->getVendorId();
+}
+
static JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{ "nativeInit", "(Lcom/android/server/hdmi/HdmiCecController;)J",
(void *) nativeInit },
- { "nativeSendCecCommand", "(JII[B)I",
- (void *) nativeSendCecCommand },
+ { "nativeSendCecCommand", "(JII[B)I", (void *) nativeSendCecCommand },
+ { "nativeAddLogicalAddress", "(JI)I", (void *) nativeAddLogicalAddress },
+ { "nativeClearLogicalAddress", "(J)V", (void *) nativeClearLogicalAddress },
+ { "nativeGetPhysicalAddress", "(J)I", (void *) nativeGetPhysicalAddress },
+ { "nativeGetVersion", "(J)I", (void *) nativeGetVersion },
+ { "nativeGetVendorId", "(J)I", (void *) nativeGetVendorId },
};
#define CLASS_PATH "com/android/server/hdmi/HdmiCecController"
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index aaa97eb..7a0d1c7 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -588,6 +588,7 @@
filter.addAction(Intent.ACTION_USER_REMOVED);
filter.addAction(Intent.ACTION_USER_STARTED);
filter.addAction(KeyChain.ACTION_STORAGE_CHANGED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
@@ -3081,7 +3082,7 @@
}
}
- public void forwardMatchingIntents(ComponentName who, IntentFilter filter, int flags) {
+ public void addForwardingIntentFilter(ComponentName who, IntentFilter filter, int flags) {
int callingUserId = UserHandle.getCallingUserId();
synchronized (this) {
if (who == null) {
@@ -3093,10 +3094,12 @@
long id = Binder.clearCallingIdentity();
try {
if ((flags & DevicePolicyManager.FLAG_TO_PRIMARY_USER) != 0) {
- pm.addForwardingIntentFilter(filter, callingUserId, UserHandle.USER_OWNER);
+ pm.addForwardingIntentFilter(filter, true /*removable*/, callingUserId,
+ UserHandle.USER_OWNER);
}
if ((flags & DevicePolicyManager.FLAG_TO_MANAGED_PROFILE) != 0) {
- pm.addForwardingIntentFilter(filter, UserHandle.USER_OWNER, callingUserId);
+ pm.addForwardingIntentFilter(filter, true /*removable*/, UserHandle.USER_OWNER,
+ callingUserId);
}
} catch (RemoteException re) {
// Shouldn't happen
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index f5ac178..6822ee3 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -373,8 +373,9 @@
mUEventObserver.startObserving(USB_STATE_MATCH);
mUEventObserver.startObserving(ACCESSORY_START_MATCH);
- mContext.registerReceiver(
- mBootCompletedReceiver, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+ IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ mContext.registerReceiver(mBootCompletedReceiver, filter);
mContext.registerReceiver(
mUserSwitchedReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED));
} catch (Exception e) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 045c0f6..16afc8f 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -28,6 +28,8 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.voice.IVoiceInteractionService;
@@ -88,6 +90,21 @@
private boolean mSafeMode;
private int mCurUser;
+ @Override
+ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
+ throws RemoteException {
+ try {
+ return super.onTransact(code, data, reply, flags);
+ } catch (RuntimeException e) {
+ // The activity manager only throws security exceptions, so let's
+ // log all others.
+ if (!(e instanceof SecurityException)) {
+ Slog.wtf(TAG, "VoiceInteractionManagerService Crash", e);
+ }
+ throw e;
+ }
+ }
+
public void systemRunning(boolean safeMode) {
mSafeMode = safeMode;
@@ -97,18 +114,18 @@
synchronized (this) {
mCurUser = ActivityManager.getCurrentUser();
- switchImplementationIfNeededLocked();
+ switchImplementationIfNeededLocked(false);
}
}
public void switchUser(int userHandle) {
synchronized (this) {
mCurUser = userHandle;
- switchImplementationIfNeededLocked();
+ switchImplementationIfNeededLocked(false);
}
}
- void switchImplementationIfNeededLocked() {
+ void switchImplementationIfNeededLocked(boolean force) {
if (!mSafeMode) {
String curService = Settings.Secure.getStringForUser(
mResolver, Settings.Secure.VOICE_INTERACTION_SERVICE, mCurUser);
@@ -121,7 +138,7 @@
serviceComponent = null;
}
}
- if (mImpl == null || mImpl.mUser != mCurUser
+ if (force || mImpl == null || mImpl.mUser != mCurUser
|| !mImpl.mComponent.equals(serviceComponent)) {
if (mImpl != null) {
mImpl.shutdownLocked();
@@ -138,10 +155,10 @@
}
@Override
- public void startVoiceActivity(Intent intent, String resolvedType,
- IVoiceInteractionService service, Bundle args) {
+ public void startSession(IVoiceInteractionService service, Bundle args) {
synchronized (this) {
- if (mImpl == null || service.asBinder() != mImpl.mService.asBinder()) {
+ if (mImpl == null || mImpl.mService == null
+ || service.asBinder() != mImpl.mService.asBinder()) {
throw new SecurityException(
"Caller is not the current voice interaction service");
}
@@ -149,8 +166,7 @@
final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity();
try {
- mImpl.startVoiceActivityLocked(callingPid, callingUid,
- intent, resolvedType, args);
+ mImpl.startSessionLocked(callingPid, callingUid, args);
} finally {
Binder.restoreCallingIdentity(caller);
}
@@ -158,12 +174,12 @@
}
@Override
- public int deliverNewSession(IBinder token, IVoiceInteractionSession session,
+ public boolean deliverNewSession(IBinder token, IVoiceInteractionSession session,
IVoiceInteractor interactor) {
synchronized (this) {
if (mImpl == null) {
- Slog.w(TAG, "deliverNewSession without running voice interaction service");
- return ActivityManager.START_CANCELED;
+ throw new SecurityException(
+ "deliverNewSession without running voice interaction service");
}
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
@@ -175,7 +191,43 @@
Binder.restoreCallingIdentity(caller);
}
}
+ }
+ @Override
+ public int startVoiceActivity(IBinder token, Intent intent, String resolvedType) {
+ synchronized (this) {
+ if (mImpl == null) {
+ Slog.w(TAG, "startVoiceActivity without running voice interaction service");
+ return ActivityManager.START_CANCELED;
+ }
+ final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ return mImpl.startVoiceActivityLocked(callingPid, callingUid, token,
+ intent, resolvedType);
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
+ }
+ }
+
+ @Override
+ public void finish(IBinder token) {
+ synchronized (this) {
+ if (mImpl == null) {
+ Slog.w(TAG, "finish without running voice interaction service");
+ return;
+ }
+ final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
+ final long caller = Binder.clearCallingIdentity();
+ try {
+ mImpl.finishLocked(callingPid, callingUid, token);
+ } finally {
+ Binder.restoreCallingIdentity(caller);
+ }
+ }
}
@Override
@@ -207,7 +259,7 @@
@Override public void onChange(boolean selfChange) {
synchronized (VoiceInteractionManagerServiceStub.this) {
- switchImplementationIfNeededLocked();
+ switchImplementationIfNeededLocked(false);
}
}
}
@@ -220,27 +272,25 @@
@Override
public void onHandleUserStop(Intent intent, int userHandle) {
- super.onHandleUserStop(intent, userHandle);
}
@Override
public void onPackageDisappeared(String packageName, int reason) {
- super.onPackageDisappeared(packageName, reason);
}
@Override
public void onPackageAppeared(String packageName, int reason) {
- super.onPackageAppeared(packageName, reason);
+ if (mImpl != null && packageName.equals(mImpl.mComponent.getPackageName())) {
+ switchImplementationIfNeededLocked(true);
+ }
}
@Override
public void onPackageModified(String packageName) {
- super.onPackageModified(packageName);
}
@Override
public void onSomePackagesChanged() {
- super.onSomePackagesChanged();
}
};
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 6bbd1c1..9b6daad 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -19,9 +19,11 @@
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
@@ -30,6 +32,7 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.service.voice.IVoiceInteractionService;
import android.service.voice.IVoiceInteractionSession;
@@ -37,6 +40,8 @@
import android.service.voice.VoiceInteractionService;
import android.service.voice.VoiceInteractionServiceInfo;
import android.util.Slog;
+import android.view.IWindowManager;
+import android.view.WindowManager;
import com.android.internal.app.IVoiceInteractor;
import java.io.FileDescriptor;
@@ -55,11 +60,28 @@
final IActivityManager mAm;
final VoiceInteractionServiceInfo mInfo;
final ComponentName mSessionComponentName;
+ final IWindowManager mIWindowManager;
boolean mBound = false;
IVoiceInteractionService mService;
SessionConnection mActiveSession;
+ final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
+ synchronized (mLock) {
+ if (mActiveSession != null && mActiveSession.mSession != null) {
+ try {
+ mActiveSession.mSession.closeSystemDialogs();
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ }
+ }
+ };
+
final ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
@@ -76,23 +98,26 @@
final class SessionConnection implements ServiceConnection {
final IBinder mToken = new Binder();
- final Intent mIntent;
- final String mResolvedType;
final Bundle mArgs;
boolean mBound;
IVoiceInteractionSessionService mService;
IVoiceInteractionSession mSession;
IVoiceInteractor mInteractor;
- SessionConnection(Intent intent, String resolvedType, Bundle args) {
- mIntent = intent;
- mResolvedType = resolvedType;
+ SessionConnection(Bundle args) {
mArgs = args;
Intent serviceIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
serviceIntent.setComponent(mSessionComponentName);
mBound = mContext.bindServiceAsUser(serviceIntent, this,
Context.BIND_AUTO_CREATE, new UserHandle(mUser));
- if (!mBound) {
+ if (mBound) {
+ try {
+ mIWindowManager.addWindowToken(mToken,
+ WindowManager.LayoutParams.TYPE_INPUT_METHOD);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed adding window token", e);
+ }
+ } else {
Slog.w(TAG, "Failed binding to voice interaction session service " + mComponent);
}
}
@@ -105,7 +130,7 @@
try {
mService.newSession(mToken, mArgs);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed making new session", e);
+ Slog.w(TAG, "Failed adding window token", e);
}
}
}
@@ -118,7 +143,19 @@
public void cancel() {
if (mBound) {
+ if (mSession != null) {
+ try {
+ mSession.destroy();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Voice interation session already dead");
+ }
+ }
mContext.unbindService(this);
+ try {
+ mIWindowManager.removeWindowToken(mToken);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed removing window token", e);
+ }
mBound = false;
mService = null;
mSession = null;
@@ -128,8 +165,6 @@
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("mToken="); pw.println(mToken);
- pw.print(prefix); pw.print("mIntent="); pw.println(mIntent);
- pw.print(" mResolvedType="); pw.println(mResolvedType);
pw.print(prefix); pw.print("mArgs="); pw.println(mArgs);
pw.print(prefix); pw.print("mBound="); pw.println(mBound);
if (mBound) {
@@ -155,6 +190,7 @@
Slog.w(TAG, "Voice interaction service not found: " + service);
mInfo = null;
mSessionComponentName = null;
+ mIWindowManager = null;
mValid = false;
return;
}
@@ -162,43 +198,67 @@
if (mInfo.getParseError() != null) {
Slog.w(TAG, "Bad voice interaction service: " + mInfo.getParseError());
mSessionComponentName = null;
+ mIWindowManager = null;
mValid = false;
return;
}
mValid = true;
mSessionComponentName = new ComponentName(service.getPackageName(),
mInfo.getSessionService());
+ mIWindowManager = IWindowManager.Stub.asInterface(
+ ServiceManager.getService(Context.WINDOW_SERVICE));
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ mContext.registerReceiver(mBroadcastReceiver, filter, null, handler);
}
- public void startVoiceActivityLocked(int callingPid, int callingUid, Intent intent,
- String resolvedType, Bundle args) {
+ public void startSessionLocked(int callingPid, int callingUid, Bundle args) {
if (mActiveSession != null) {
mActiveSession.cancel();
mActiveSession = null;
}
- mActiveSession = new SessionConnection(intent, resolvedType, args);
- intent.addCategory(Intent.CATEGORY_VOICE);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+ mActiveSession = new SessionConnection(args);
}
- public int deliverNewSessionLocked(int callingPid, int callingUid, IBinder token,
+ public boolean deliverNewSessionLocked(int callingPid, int callingUid, IBinder token,
IVoiceInteractionSession session, IVoiceInteractor interactor) {
+ if (mActiveSession == null || token != mActiveSession.mToken) {
+ Slog.w(TAG, "deliverNewSession does not match active session");
+ return false;
+ }
+ mActiveSession.mSession = session;
+ mActiveSession.mInteractor = interactor;
+ return true;
+ }
+
+ public int startVoiceActivityLocked(int callingPid, int callingUid, IBinder token,
+ Intent intent, String resolvedType) {
try {
if (mActiveSession == null || token != mActiveSession.mToken) {
- Slog.w(TAG, "deliverNewSession does not match active session");
+ Slog.w(TAG, "startVoiceActivity does not match active session");
return ActivityManager.START_CANCELED;
}
- mActiveSession.mSession = session;
- mActiveSession.mInteractor = interactor;
+ intent = new Intent(intent);
+ intent.addCategory(Intent.CATEGORY_VOICE);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
return mAm.startVoiceActivity(mComponent.getPackageName(), callingPid, callingUid,
- mActiveSession.mIntent, mActiveSession.mResolvedType,
- mActiveSession.mSession, mActiveSession.mInteractor,
+ intent, resolvedType, mActiveSession.mSession, mActiveSession.mInteractor,
0, null, null, null, mUser);
} catch (RemoteException e) {
throw new IllegalStateException("Unexpected remote error", e);
}
}
+
+ public void finishLocked(int callingPid, int callingUid, IBinder token) {
+ if (mActiveSession == null || token != mActiveSession.mToken) {
+ Slog.w(TAG, "finish does not match active session");
+ return;
+ }
+ mActiveSession.cancel();
+ mActiveSession = null;
+ }
+
public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!mValid) {
pw.print(" NOT VALID: ");
@@ -234,5 +294,8 @@
mContext.unbindService(mConnection);
mBound = false;
}
+ if (mValid) {
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ }
}
}
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 992ef4b..a016933 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -701,4 +701,21 @@
VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
throw new UnsupportedOperationException();
}
+
+ /**
+ * @hide
+ */
+ @Override
+ public void addForwardingIntentFilter(IntentFilter filter, boolean removable, int userIdOrig,
+ int userIdDest) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void clearForwardingIntentFilters(int userIdOrig) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 5c2583b..af0d0ad 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -288,6 +288,15 @@
</activity>
<activity
+ android:name="CirclePropActivity"
+ android:label="Draw/Circle Props">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.test.hwui.TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity
android:name="ClearActivity"
android:label="Window/Clear">
<intent-filter>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
new file mode 100644
index 0000000..5c273de1
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java
@@ -0,0 +1,146 @@
+/*
+ * 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.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.CanvasProperty;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.os.Bundle;
+import android.os.Trace;
+import android.view.HardwareCanvas;
+import android.view.RenderNodeAnimator;
+import android.view.View;
+import android.webkit.WebChromeClient;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.LinearLayout;
+import android.widget.LinearLayout.LayoutParams;
+import android.widget.ProgressBar;
+
+import java.util.ArrayList;
+
+public class CirclePropActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final LinearLayout layout = new LinearLayout(this);
+ layout.setOrientation(LinearLayout.VERTICAL);
+
+ ProgressBar spinner = new ProgressBar(this, null, android.R.attr.progressBarStyleLarge);
+ layout.addView(spinner, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
+ // For testing with a functor in the tree
+// WebView wv = new WebView(this);
+// wv.setWebViewClient(new WebViewClient());
+// wv.setWebChromeClient(new WebChromeClient());
+// wv.loadUrl("http://theverge.com");
+// layout.addView(wv, new LayoutParams(LayoutParams.MATCH_PARENT, 100));
+
+ layout.addView(new CircleView(this),
+ new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+
+ setContentView(layout);
+ }
+
+ static class CircleView extends View {
+ static final int DURATION = 500;
+
+ private boolean mToggle = false;
+ ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<RenderNodeAnimator>();
+
+ CanvasProperty<Float> mX;
+ CanvasProperty<Float> mY;
+ CanvasProperty<Float> mRadius;
+ CanvasProperty<Paint> mPaint;
+
+ CircleView(Context c) {
+ super(c);
+ setClickable(true);
+
+ mX = CanvasProperty.createFloat(200.0f);
+ mY = CanvasProperty.createFloat(200.0f);
+ mRadius = CanvasProperty.createFloat(150.0f);
+
+ Paint p = new Paint();
+ p.setAntiAlias(true);
+ p.setColor(0xFFFF0000);
+ p.setStyle(Style.STROKE);
+ p.setStrokeWidth(60.0f);
+ mPaint = CanvasProperty.createPaint(p);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (canvas.isHardwareAccelerated()) {
+ HardwareCanvas hwcanvas = (HardwareCanvas) canvas;
+ hwcanvas.drawCircle(mX, mY, mRadius, mPaint);
+ }
+ }
+
+ @Override
+ public boolean performClick() {
+ for (int i = 0; i < mRunningAnimations.size(); i++) {
+ mRunningAnimations.get(i).cancel();
+ }
+ mRunningAnimations.clear();
+
+ mToggle = !mToggle;
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mX, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 400.0f : 200.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mY, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 600.0f : 200.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mRadius, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 250.0f : 150.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mPaint, RenderNodeAnimator.PAINT_ALPHA,
+ RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 64.0f : 255.0f));
+
+ mRunningAnimations.add(new RenderNodeAnimator(
+ mPaint, RenderNodeAnimator.PAINT_STROKE_WIDTH,
+ RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 5.0f : 60.0f));
+
+ for (int i = 0; i < mRunningAnimations.size(); i++) {
+ mRunningAnimations.get(i).start(this);
+ }
+
+ if (mToggle) {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "pretendBusy");
+ try {
+ Thread.sleep(DURATION);
+ } catch (InterruptedException e) {
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+ });
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
index 8c02539..a3f4ddc 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/SmallCircleActivity.java
@@ -57,7 +57,7 @@
mPaint = new Paint();
mPaint.setAntiAlias(true);
- mPaint.setColor(0xffffffff);
+ mPaint.setColor(0xff00ffff);
}
@Override
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
index 1d209dd..8f9cf58 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
@@ -19,8 +19,6 @@
public class MainActivity extends Activity implements OnItemClickListener {
- static final int TRANSLATION_Y = 1;
- static final int DELTA_TYPE_DELTA = 1;
static final int DURATION = 400;
static final String KEY_NAME = "name";
@@ -75,7 +73,7 @@
float delta = (pos - clickedPosition) * 1.1f;
if (delta == 0) delta = -1;
RenderNodeAnimator animator = new RenderNodeAnimator(
- TRANSLATION_Y, DELTA_TYPE_DELTA, dy * delta);
+ RenderNodeAnimator.TRANSLATION_Y, RenderNodeAnimator.DELTA_TYPE_DELTA, dy * delta);
animator.setDuration(DURATION);
animator.start(child);
}
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
index 88ae398..7ba01b1 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
@@ -22,7 +22,7 @@
import android.widget.GridLayout;
@SuppressWarnings({"UnusedDeclaration"})
-public class VectorDrawable01 extends Activity implements View.OnClickListener {
+public class VectorDrawable01 extends Activity {
private static final String LOGCAT = "VectorDrawable1";
int[] icon = {
R.drawable.vector_drawable01,
@@ -61,28 +61,10 @@
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/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
index 3929298..b918cdd 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -25,7 +25,7 @@
import java.text.DecimalFormat;
@SuppressWarnings({"UnusedDeclaration"})
-public class VectorDrawablePerformance extends Activity implements View.OnClickListener {
+public class VectorDrawablePerformance extends Activity {
private static final String LOGCAT = "VectorDrawable1";
protected int[] icon = {
R.drawable.vector_drawable01,
@@ -76,7 +76,6 @@
button.setWidth(200);
button.setBackgroundResource(icon[i]);
container.addView(button);
- button.setOnClickListener(this);
}
setContentView(scrollView);
time = android.os.SystemClock.elapsedRealtimeNanos()-time;
@@ -85,10 +84,4 @@
t.setBackgroundColor(0xFF000000);
container.addView(t);
}
-
- @Override
- public void onClick(View v) {
- VectorDrawable d = (VectorDrawable) v.getBackground();
- d.start();
- }
}
diff --git a/tests/VoiceInteraction/res/layout/voice_interaction_session.xml b/tests/VoiceInteraction/res/layout/voice_interaction_session.xml
new file mode 100644
index 0000000..9fcbf3e
--- /dev/null
+++ b/tests/VoiceInteraction/res/layout/voice_interaction_session.xml
@@ -0,0 +1,38 @@
+<?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_width="fill_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:background="#ffffffff"
+ >
+
+ <TextView android:id="@+id/text"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="32dp"
+ />
+
+ <Button android:id="@+id/start"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/start"
+ />
+
+</LinearLayout>
+
+
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
index 008d97b..d40b05f 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
@@ -17,6 +17,7 @@
package com.android.test.voiceinteraction;
import android.content.Intent;
+import android.os.Bundle;
import android.service.voice.VoiceInteractionService;
import android.util.Log;
@@ -31,7 +32,9 @@
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- startVoiceActivity(new Intent(this, TestInteractionActivity.class), null);
+ Bundle args = new Bundle();
+ args.putParcelable("intent", new Intent(this, TestInteractionActivity.class));
+ startSession(args);
stopSelf(startId);
return START_NOT_STICKY;
}
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
index 0fc563b..a3af284 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
@@ -17,18 +17,59 @@
package com.android.test.voiceinteraction;
import android.content.Context;
+import android.content.Intent;
import android.os.Bundle;
import android.service.voice.VoiceInteractionSession;
import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
-public class MainInteractionSession extends VoiceInteractionSession {
+public class MainInteractionSession extends VoiceInteractionSession
+ implements View.OnClickListener {
static final String TAG = "MainInteractionSession";
- final Bundle mArgs;
+ Intent mStartIntent;
+ View mContentView;
+ TextView mText;
+ Button mStartButton;
- MainInteractionSession(Context context, Bundle args) {
+ Request mPendingRequest;
+ boolean mPendingConfirm;
+
+ MainInteractionSession(Context context) {
super(context);
- mArgs = args;
+ }
+
+ @Override
+ public void onCreate(Bundle args) {
+ super.onCreate(args);
+ showWindow();
+ mStartIntent = args.getParcelable("intent");
+ }
+
+ @Override
+ public View onCreateContentView() {
+ mContentView = getLayoutInflater().inflate(R.layout.voice_interaction_session, null);
+ mText = (TextView)mContentView.findViewById(R.id.text);
+ mStartButton = (Button)mContentView.findViewById(R.id.start);
+ mStartButton.setOnClickListener(this);
+ return mContentView;
+ }
+
+ public void onClick(View v) {
+ if (mPendingRequest == null) {
+ mStartButton.setEnabled(false);
+ startVoiceActivity(mStartIntent);
+ } else {
+ if (mPendingConfirm) {
+ mPendingRequest.sendConfirmResult(true, null);
+ } else {
+ mPendingRequest.sendCommandResult(true, null);
+ }
+ mPendingRequest = null;
+ mStartButton.setText("Start");
+ }
}
@Override
@@ -38,14 +79,22 @@
@Override
public void onConfirm(Caller caller, Request request, String prompt, Bundle extras) {
- Log.i(TAG, "onConform: prompt=" + prompt + " extras=" + extras);
- request.sendConfirmResult(true, null);
+ Log.i(TAG, "onConfirm: prompt=" + prompt + " extras=" + extras);
+ mText.setText(prompt);
+ mStartButton.setEnabled(true);
+ mStartButton.setText("Confirm");
+ mPendingRequest = request;
+ mPendingConfirm = true;
}
@Override
public void onCommand(Caller caller, Request request, String command, Bundle extras) {
Log.i(TAG, "onCommand: command=" + command + " extras=" + extras);
- request.sendCommandResult(true, null);
+ mText.setText("Command: " + command);
+ mStartButton.setEnabled(true);
+ mStartButton.setText("Finish Command");
+ mPendingRequest = request;
+ mPendingConfirm = false;
}
@Override
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSessionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSessionService.java
index 8864d71..7cf8178 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSessionService.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSessionService.java
@@ -23,6 +23,6 @@
public class MainInteractionSessionService extends VoiceInteractionSessionService {
@Override
public VoiceInteractionSession onNewSession(Bundle args) {
- return new MainInteractionSession(this, args);
+ return new MainInteractionSession(this);
}
}
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index d0581f6..1348be3 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -1261,12 +1261,13 @@
while ((err=it.next()) == NO_ERROR) {
String8 src = it.getFile()->getPrintableSource();
err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
- if (err != NO_ERROR) {
+ if (err == NO_ERROR) {
+ ResXMLTree block;
+ block.setTo(it.getFile()->getData(), it.getFile()->getSize(), true);
+ checkForIds(src, block);
+ } else {
hasErrors = true;
}
- ResXMLTree block;
- block.setTo(it.getFile()->getData(), it.getFile()->getSize(), true);
- checkForIds(src, block);
}
if (err < NO_ERROR) {
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index b445b8a..6eab65b 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -865,6 +865,21 @@
pseudoBidiParams.country[0] = 'X';
pseudoBidiParams.country[1] = 'B';
+ // We should skip resources for pseudolocales if they were
+ // already added automatically. This is a fix for a transition period when
+ // manually pseudolocalized resources may be expected.
+ // TODO: remove this check after next SDK version release.
+ if ((bundle->getPseudolocalize() & PSEUDO_ACCENTED &&
+ curParams.locale == pseudoParams.locale) ||
+ (bundle->getPseudolocalize() & PSEUDO_BIDI &&
+ curParams.locale == pseudoBidiParams.locale)) {
+ SourcePos(in->getPrintableSource(), 0).warning(
+ "Resource file %s is skipped as pseudolocalization"
+ " was done automatically.",
+ in->getPrintableSource().string());
+ return NO_ERROR;
+ }
+
while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
if (code == ResXMLTree::START_TAG) {
const String16* curTag = NULL;