Snap for 4590521 from d895f9374c to pi-release
Change-Id: I1b3126ea3441447022dea3576d8a3e0d9d7ed98d
This commit is contained in:
34
res/drawable/ic_event.xml
Normal file
34
res/drawable/ic_event.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<!--
|
||||
Copyright (C) 2018 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape android:shape="oval">
|
||||
<solid
|
||||
android:color="?android:attr/colorAccent" />
|
||||
<size
|
||||
android:width="@dimen/dashboard_tile_image_size"
|
||||
android:height="@dimen/dashboard_tile_image_size" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:width="@dimen/dashboard_tile_foreground_image_size"
|
||||
android:height="@dimen/dashboard_tile_foreground_image_size"
|
||||
android:start="@dimen/dashboard_tile_foreground_image_inset"
|
||||
android:top="@dimen/dashboard_tile_foreground_image_inset"
|
||||
android:drawable="@drawable/ic_event_white" />
|
||||
</layer-list>
|
||||
25
res/drawable/ic_event_white.xml
Normal file
25
res/drawable/ic_event_white.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2018 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24.0dp"
|
||||
android:height="24.0dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M17.0,12.0l-5.0,0.0l0.0,5.0l5.0,0.0l0.0,-5.0zM16.0,1.0l0.0,2.0L8.0,3.0L8.0,1.0L6.0,1.0l0.0,2.0L5.0,3.0c-1.11,0.0 -1.9,0.9 -1.99,2.0L3.0,19.0c0.0,1.0 0.89,2.0 2.0,2.0l14.0,0.0c1.1,0.0 2.0,-0.9 2.0,-2.0L21.0,5.0c0.0,-1.1 -0.9,-2.0 -2.0,-2.0l-1.0,0.0L18.0,1.0l-2.0,0.0zm3.0,18.0L5.0,19.0L5.0,8.0l14.0,0.0l0.0,11.0z"/>
|
||||
</vector>
|
||||
34
res/drawable/ic_timelapse.xml
Normal file
34
res/drawable/ic_timelapse.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<!--
|
||||
Copyright (C) 2018 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item>
|
||||
<shape android:shape="oval">
|
||||
<solid
|
||||
android:color="?android:attr/colorAccent" />
|
||||
<size
|
||||
android:width="@dimen/dashboard_tile_image_size"
|
||||
android:height="@dimen/dashboard_tile_image_size" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:width="@dimen/dashboard_tile_foreground_image_size"
|
||||
android:height="@dimen/dashboard_tile_foreground_image_size"
|
||||
android:start="@dimen/dashboard_tile_foreground_image_inset"
|
||||
android:top="@dimen/dashboard_tile_foreground_image_inset"
|
||||
android:drawable="@drawable/ic_timelapse_white" />
|
||||
</layer-list>
|
||||
25
res/drawable/ic_timelapse_white.xml
Normal file
25
res/drawable/ic_timelapse_white.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2018 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24.0dp"
|
||||
android:height="24.0dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M16.24,7.76C15.07,6.59 13.54,6.0 12.0,6.0l0.0,6.0l-4.24,4.24c2.34,2.34 6.14,2.34 8.49,0.0 2.34,-2.34 2.34,-6.14 -0.01,-8.48zM12.0,2.0C6.48,2.0 2.0,6.48 2.0,12.0s4.48,10.0 10.0,10.0 10.0,-4.48 10.0,-10.0S17.52,2.0 12.0,2.0zm0.0,18.0c-4.42,0.0 -8.0,-3.58 -8.0,-8.0s3.58,-8.0 8.0,-8.0 8.0,3.58 8.0,8.0 -3.58,8.0 -8.0,8.0z"/>
|
||||
</vector>
|
||||
47
res/layout/battery_saver_settings_button.xml
Normal file
47
res/layout/battery_saver_settings_button.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="bottom"
|
||||
android:paddingStart="72dp"
|
||||
android:paddingEnd="72dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<Button
|
||||
android:id="@+id/battery_saver_on_button"
|
||||
style="@style/ActionPrimaryButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/battery_saver_button_turn_on"
|
||||
android:paddingEnd="8dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/battery_saver_off_button"
|
||||
style="@style/ActionSecondaryButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/battery_saver_button_turn_off"
|
||||
android:paddingEnd="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2017 The Android Open Source Project
|
||||
<!-- Copyright (C) 2018 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -14,10 +14,14 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<View
|
||||
<!-- Settings button -->
|
||||
<ImageView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/feedback_popup"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:visibility="gone">
|
||||
</View>
|
||||
android:id="@+id/settings_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_settings"
|
||||
android:contentDescription="@string/settings_button" />
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2016 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<include layout="@layout/search_icon_view"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||
android:ellipsize="marquee"/>
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceListItemSecondary"/>
|
||||
|
||||
<include layout="@layout/search_breadcrumb_view"/>
|
||||
</LinearLayout>
|
||||
|
||||
<Switch
|
||||
android:id="@+id/switchView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="top"
|
||||
android:paddingStart="16dp"/>
|
||||
</LinearLayout>
|
||||
@@ -1,54 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2016 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<include layout="@layout/search_icon_view"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||
android:ellipsize="marquee"/>
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
||||
android:ellipsize="marquee"/>
|
||||
|
||||
<include layout="@layout/search_breadcrumb_view"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -1,107 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2016 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/search_panel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/search_bar_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/suggestion_condition_background">
|
||||
<android.support.v7.widget.CardView
|
||||
android:id="@+id/search_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/search_bar_margin"
|
||||
app:cardCornerRadius="2dp"
|
||||
app:cardBackgroundColor="?android:attr/colorBackground"
|
||||
app:cardElevation="2dp">
|
||||
<Toolbar
|
||||
android:id="@+id/search_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/search_bar_height"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentInsetStart="0dp"
|
||||
android:contentInsetStartWithNavigation="0dp"
|
||||
android:theme="?android:attr/actionBarTheme">
|
||||
<SearchView
|
||||
android:id="@+id/search_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:iconifiedByDefault="false"
|
||||
android:imeOptions="actionSearch|flagNoExtractUi"
|
||||
android:searchIcon="@null"/>
|
||||
</Toolbar>
|
||||
</android.support.v7.widget.CardView>
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/layout_results"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Padding is included in the background -->
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/list_results"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/dashboard_padding_start"
|
||||
android:paddingEnd="@dimen/dashboard_padding_end"
|
||||
android:paddingTop="@dimen/dashboard_padding_top"
|
||||
android:paddingBottom="@dimen/dashboard_padding_bottom"
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
android:scrollbars="vertical"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/no_results_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingTop="35dp"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<Space
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?android:attr/actionBarSize"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:src="@drawable/empty_search_results"/>
|
||||
|
||||
<TextView
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:paddingTop="24dp"
|
||||
android:textSize="18sp"
|
||||
android:text="@string/search_settings_no_results"
|
||||
android:gravity="center"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<include layout="@layout/search_feedback"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -43,7 +43,6 @@
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentInsetStartWithNavigation="64dp"
|
||||
android:navigationIcon="@drawable/ic_search_24dp"
|
||||
android:navigationContentDescription="@string/search_menu"
|
||||
android:theme="?android:attr/actionBarTheme">
|
||||
<TextView
|
||||
android:id="@+id/search_action_bar_title"
|
||||
|
||||
@@ -17,31 +17,25 @@
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="bottom"
|
||||
android:paddingStart="72dp"
|
||||
android:paddingEnd="72dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Button
|
||||
android:id="@+id/zen_mode_settings_turn_on_button"
|
||||
style="@style/ActionPrimaryButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="@dimen/screen_margin_sides"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:text="@string/zen_mode_button_turn_on"
|
||||
android:paddingEnd="8dp" />
|
||||
android:text="@string/zen_mode_button_turn_on"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/zen_mode_settings_turn_off_button"
|
||||
style="@style/ActionSecondaryButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="@dimen/screen_margin_sides"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:text="@string/zen_mode_button_turn_off"
|
||||
android:paddingEnd="8dp" />
|
||||
android:text="@string/zen_mode_button_turn_off" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -23,10 +23,9 @@
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
/>
|
||||
android:layout_width="@dimen/app_icon_size"
|
||||
android:layout_height="@dimen/app_icon_size"
|
||||
android:layout_gravity="center"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
<dimen name="support_escalation_card_padding_end">56dp</dimen>
|
||||
|
||||
<!-- Suggestion cards-->
|
||||
<dimen name="suggestion_card_width_one_card">384dp</dimen>
|
||||
<dimen name="suggestion_card_width_two_cards">188dp</dimen>
|
||||
<dimen name="suggestion_card_width_multiple_cards">180dp</dimen>
|
||||
<dimen name="suggestion_card_padding_bottom_one_card">22dp</dimen>
|
||||
|
||||
|
||||
@@ -304,8 +304,6 @@
|
||||
|
||||
<!-- Suggestion cards size and padding -->
|
||||
<dimen name="suggestion_card_icon_size">24dp</dimen>
|
||||
<dimen name="suggestion_card_width_one_card">332dp</dimen>
|
||||
<dimen name="suggestion_card_width_two_cards">162dp</dimen>
|
||||
<dimen name="suggestion_card_width_multiple_cards">156dp</dimen>
|
||||
<dimen name="suggestion_card_outer_margin">14dp</dimen>
|
||||
<dimen name="suggestion_card_inner_margin">12dp</dimen>
|
||||
|
||||
@@ -2423,13 +2423,6 @@
|
||||
|
||||
<!-- Main Settings screen, setting option name to go into search settings -->
|
||||
<string name="search_settings">Search</string>
|
||||
<!-- Main Settings screen, setting option summary to go into search settings -->
|
||||
<string name="search_settings_summary">Manage search settings and history</string>
|
||||
<!-- There are no search results for the user's search [CHAR LIMIT=NONE]-->
|
||||
<string name="search_settings_no_results">No results</string>
|
||||
|
||||
<!-- Button to clear all search history in Settings [CHAR LIMIT=40]-->
|
||||
<string name="search_clear_history">Clear history</string>
|
||||
|
||||
<!-- Display settings --><skip/>
|
||||
<!-- Sound & display settings screen, section header for settings related to display -->
|
||||
@@ -4431,6 +4424,12 @@
|
||||
<string name="accessibility_autoclick_preference_title">Click after pointer stops moving</string>
|
||||
<!-- Title for accessibility preference for configuring amount of time that has to pass after pointer stops moving before click action can be performed (if automatic click after pointer stops moving feature is enabled). [CHAR LIMIT=NONE] -->
|
||||
<string name="accessibility_autoclick_delay_preference_title">Delay before click</string>
|
||||
<!-- Title for accessibility preference screen for configuring vibrations. -->
|
||||
<string name="accessibility_vibration_settings_title">Vibration</string>
|
||||
<!-- Title for accessibility preference for configuring notification vibrations. -->
|
||||
<string name="accessibility_notification_vibration_title">Ring & notification vibration</string>
|
||||
<!-- Title for accessibility preference for configuring touch feedback vibrations. -->
|
||||
<string name="accessibility_touch_vibration_title">Touch vibration</string>
|
||||
<!-- Used in the acessibilty service settings to control turning on/off the service entirely -->
|
||||
<string name="accessibility_service_master_switch_title">Use service</string>
|
||||
<!-- Used in the Color correction settings screen to control turning on/off the feature entirely -->
|
||||
@@ -4474,6 +4473,30 @@
|
||||
<item quantity="other">Very long delay (<xliff:g id="click_delay_label" example="200">%1$d</xliff:g> ms)</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Summary for vibration settings preference when ring & notification are set to off-->
|
||||
<string name="accessibility_vibration_summary_off">Ring & notification set to off</string>
|
||||
|
||||
<!-- Summary for vibration settings preference when ring & notification are set to low-->
|
||||
<string name="accessibility_vibration_summary_low">Ring & notification set to low</string>
|
||||
|
||||
<!-- Summary for vibration settings preference when ring & notification are set to medium-->
|
||||
<string name="accessibility_vibration_summary_medium">Ring & notification set to medium</string>
|
||||
|
||||
<!-- Summary for vibration settings preference when ring & notification are set to high-->
|
||||
<string name="accessibility_vibration_summary_high">Ring & notification set to high</string>
|
||||
|
||||
<!-- Label describing an option turning vibrations off. [CHAR LIMIT=15] -->
|
||||
<string name="accessibility_vibration_intensity_off">Off</string>
|
||||
|
||||
<!-- Label describing a low intensity vibration option. [CHAR LIMIT=15] -->
|
||||
<string name="accessibility_vibration_intensity_low">Low</string>
|
||||
|
||||
<!-- Label describing a medium intensity vibration option. [CHAR LIMIT=15] -->
|
||||
<string name="accessibility_vibration_intensity_medium">Medium</string>
|
||||
|
||||
<!-- Label describing a high intensity vibration option. [CHAR LIMIT=15] -->
|
||||
<string name="accessibility_vibration_intensity_high">High</string>
|
||||
|
||||
<!-- Title for accessibility menu item to lauch a settings activity. [CHAR LIMIT=15] -->
|
||||
<string name="accessibility_menu_item_settings">Settings</string>
|
||||
|
||||
@@ -5136,8 +5159,17 @@
|
||||
<!-- Label for dex2oat process in battery usage used for the optimization of one or more apps -->
|
||||
<string name="process_dex2oat_label">App optimization</string>
|
||||
|
||||
<!-- [CHAR_LIMIT=40] Battery saver: Label for feature, title + menu item -->
|
||||
<string name="battery_saver">Battery Saver</string>
|
||||
<!-- Battery saver: Label for feature, title + menu item [CHAR_LIMIT=40] -->
|
||||
<string name="battery_saver">Reduced power mode</string>
|
||||
|
||||
<!-- Battery saver: Label for preference to turn on battery saver automatically when battery is low [CHAR_LIMIT=40] -->
|
||||
<string name="battery_saver_auto_title">Schedule</string>
|
||||
|
||||
<!-- Battery saver: Summary for preference to turn on battery saver automatically when battery is low [CHAR_LIMIT=40] -->
|
||||
<string name="battery_saver_auto_summary">Turn on Reduced power mode automatically when battery is low</string>
|
||||
|
||||
<!-- Battery saver: Label for seekbar to change battery saver threshold [CHAR_LIMIT=40] -->
|
||||
<string name="battery_saver_seekbar_title">Turn on automatically at <xliff:g id="percent">%1$s</xliff:g></string>
|
||||
|
||||
<!-- Used in the Battery Saver settings screen to control turning on/off the feature entirely -->
|
||||
<string name="battery_saver_master_switch_title">Use Battery Saver</string>
|
||||
@@ -6972,6 +7004,21 @@
|
||||
<!-- [CHAR LIMIT=20] Accessibility string for current zen mode and selected exit condition. A template that simply concatenates existing mode string and the current condition description. -->
|
||||
<string name="zen_mode_and_condition"><xliff:g id="zen_mode" example="Priority interruptions only">%1$s</xliff:g>. <xliff:g id="exit_condition" example="For one hour">%2$s</xliff:g></string>
|
||||
|
||||
<!-- Sound settings screen, summary format of do not disturb when on. [CHAR LIMIT=NONE] -->
|
||||
<string name="zen_mode_sound_summary_on">On / <xliff:g name="dnd_summary" example="No sound except alarms and media">%1$s</xliff:g></string>
|
||||
|
||||
<!-- Sound settings screen, summary format of do not disturb when off with extra information. [CHAR LIMIT=NONE] -->
|
||||
<string name="zen_mode_sound_summary_off_with_info">Off / <xliff:g name="dnd_summary" example="1 rule can turn on automatically">%1$s</xliff:g></string>
|
||||
|
||||
<!-- Sound settings screen, summary format of do not disturb when off with no extra information. [CHAR LIMIT=NONE] -->
|
||||
<string name="zen_mode_sound_summary_off">Off</string>
|
||||
|
||||
<!-- Summary for the Sound Do not Disturb option when at least one automatic rules is enabled. [CHAR LIMIT=NONE]-->
|
||||
<plurals name="zen_mode_sound_summary_summary_off_info">
|
||||
<item quantity="one">1 rule can turn on automatically</item>
|
||||
<item quantity="other"><xliff:g id="on_count" example="3">%d</xliff:g> rules can turn on automatically</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Work Sounds: Work sound settings section header. [CHAR LIMIT=50] -->
|
||||
<string name="sound_work_settings">Work profile sounds</string>
|
||||
|
||||
@@ -7106,10 +7153,10 @@
|
||||
summary on the channel page-->
|
||||
|
||||
<!-- [CHAR LIMIT=100] Notification Importance: min importance level description -->
|
||||
<string name="notification_importance_min">No sound or visual interruption</string>
|
||||
<string name="notification_importance_min">Show silently and minimize</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] Notification Importance: low importance level description -->
|
||||
<string name="notification_importance_low">No sound</string>
|
||||
<string name="notification_importance_low">Show silently</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] Notification Importance: normal importance level description -->
|
||||
<string name="notification_importance_default">Make sound</string>
|
||||
@@ -8695,6 +8742,12 @@
|
||||
<!-- [CHAR_LIMIT=NONE] Battery saver: Description for automatic entry option: pct% battery -->
|
||||
<string name="battery_saver_desc_turn_on_auto_pct">Turn on automatically at %1$s battery</string>
|
||||
|
||||
<!-- Battery saver: Label for button that will turn on battery saver. [CHAR LIMIT=30] -->
|
||||
<string name="battery_saver_button_turn_on">Turn on now</string>
|
||||
|
||||
<!-- Battery saver: Label for button that will turn off battery saver. [CHAR LIMIT=30] -->
|
||||
<string name="battery_saver_button_turn_off">Turn off now</string>
|
||||
|
||||
<!-- [CHAR_LIMIT=NONE] Label for when app is ignoring battery optimizations -->
|
||||
<string name="not_battery_optimizing">Not using battery optimization</string>
|
||||
|
||||
@@ -9249,6 +9302,9 @@
|
||||
<!-- Help URI, USB Audio [DO NOT TRANSLATE] -->
|
||||
<string name="help_url_audio_accessory_not_supported" translatable="false"></string>
|
||||
|
||||
<!-- Help URI, battery saver page [DO NOT TRANSLATE] -->
|
||||
<string name="help_url_battery_saver_settings" translatable="false"></string>
|
||||
|
||||
<!-- Title label for new device suggestion, which is displayed in Settings homepage [CHAR LIMIT=100] -->
|
||||
<string name="new_device_suggestion_title">What\'s new and exciting?</string>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2017 The Android Open Source Project
|
||||
Copyright (C) 2018 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -15,12 +15,6 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<TextView
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/breadcrumb"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="5dp"
|
||||
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:ellipsize="marquee"/>
|
||||
android:title="@string/accessibility_notification_vibration_title" />
|
||||
@@ -93,6 +93,12 @@
|
||||
android:entries="@array/long_press_timeout_selector_titles"
|
||||
android:entryValues="@array/long_press_timeout_selector_values"
|
||||
android:persistent="false"/>
|
||||
|
||||
<Preference
|
||||
android:fragment="com.android.settings.accessibility.VibrationSettings"
|
||||
android:key="vibration_preference_screen"
|
||||
android:title="@string/accessibility_vibration_settings_title" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
|
||||
20
res/xml/accessibility_touch_vibration_settings.xml
Normal file
20
res/xml/accessibility_touch_vibration_settings.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018 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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:title="@string/accessibility_touch_vibration_title" />
|
||||
31
res/xml/accessibility_vibration_settings.xml
Normal file
31
res/xml/accessibility_vibration_settings.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2018 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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:key="accessibility_settings_screen"
|
||||
android:title="@string/accessibility_vibration_settings_title"
|
||||
android:persistent="true">
|
||||
|
||||
<Preference
|
||||
android:fragment="com.android.settings.accessibility.NotificationVibrationPreferenceFragment"
|
||||
android:key="notification_vibration_preference_screen"
|
||||
android:title="@string/accessibility_notification_vibration_title" />
|
||||
|
||||
<Preference
|
||||
android:fragment="com.android.settings.accessibility.TouchVibrationPreferenceFragment"
|
||||
android:key="touch_vibration_preference_screen"
|
||||
android:title="@string/accessibility_touch_vibration_title" />
|
||||
</PreferenceScreen>
|
||||
@@ -14,14 +14,32 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:title="@string/battery_saver"
|
||||
android:key="battery_saver">
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:title="@string/battery_saver"
|
||||
android:key="battery_saver">
|
||||
|
||||
<!-- Turn on automatically -->
|
||||
<DropDownPreference
|
||||
android:key="turn_on_automatically"
|
||||
android:title="@string/battery_saver_turn_on_automatically_title"
|
||||
android:summary="%s" />
|
||||
<SwitchPreference
|
||||
android:key="auto_battery_saver"
|
||||
android:title="@string/battery_saver_auto_title"
|
||||
android:summary="@string/battery_saver_auto_summary"/>
|
||||
<com.android.settings.widget.SeekBarPreference
|
||||
android:key="battery_saver_seek_bar"
|
||||
android:title="@string/battery_saver_seekbar_title"
|
||||
android:max="75"
|
||||
android:min="5"/>
|
||||
<com.android.settings.applications.LayoutPreference
|
||||
android:key="battery_saver_button_container"
|
||||
android:selectable="false"
|
||||
android:layout="@layout/battery_saver_settings_button"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="battery_saver_footer">
|
||||
<com.android.settingslib.widget.FooterPreference
|
||||
android:key="battery_saver_footer_preference"
|
||||
android:title="@*android:string/battery_saver_description"
|
||||
android:selectable="false"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
<com.android.settings.applications.LayoutPreference
|
||||
android:key="battery_header"
|
||||
android:selectable="true"
|
||||
android:selectable="false"
|
||||
android:layout="@layout/battery_header"/>
|
||||
|
||||
<PreferenceCategory
|
||||
@@ -34,7 +34,7 @@
|
||||
android:key="power_management">
|
||||
|
||||
<com.android.settings.widget.MasterSwitchPreference
|
||||
android:fragment="com.android.settings.fuelgauge.BatterySaverSettings"
|
||||
android:fragment="com.android.settings.fuelgauge.batterysaver.BatterySaverSettings"
|
||||
android:key="battery_saver_summary"
|
||||
android:title="@string/battery_saver"/>
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
android:title="@string/battery_power_management">
|
||||
|
||||
<com.android.settings.widget.MasterSwitchPreference
|
||||
android:fragment="com.android.settings.fuelgauge.BatterySaverSettings"
|
||||
android:fragment="com.android.settings.fuelgauge.batterysaver.BatterySaverSettings"
|
||||
android:key="battery_saver_summary"
|
||||
android:title="@string/battery_saver"/>
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.Fragment;
|
||||
@@ -329,6 +331,7 @@ public class SettingsActivity extends SettingsDrawerActivity
|
||||
// and goes to the search UI. Also set the background to null so there's no ripple.
|
||||
View navView = toolbar.getNavigationView();
|
||||
navView.setClickable(false);
|
||||
navView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||
navView.setBackground(null);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import static android.os.Vibrator.VibrationIntensity;
|
||||
|
||||
import android.accessibilityservice.AccessibilityServiceInfo;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.ComponentName;
|
||||
@@ -28,6 +30,7 @@ import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.UserHandle;
|
||||
import android.os.Vibrator;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.provider.Settings;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
@@ -111,6 +114,8 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
|
||||
"tts_settings_preference";
|
||||
private static final String AUTOCLICK_PREFERENCE_SCREEN =
|
||||
"autoclick_preference_screen";
|
||||
private static final String VIBRATION_PREFERENCE_SCREEN =
|
||||
"vibration_preference_screen";
|
||||
|
||||
@VisibleForTesting static final String TOGGLE_INVERSION_PREFERENCE =
|
||||
"toggle_inversion_preference";
|
||||
@@ -215,6 +220,7 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
|
||||
private Preference mAutoclickPreferenceScreen;
|
||||
private Preference mAccessibilityShortcutPreferenceScreen;
|
||||
private Preference mDisplayDaltonizerPreferenceScreen;
|
||||
private Preference mVibrationPreferenceScreen;
|
||||
private SwitchPreference mToggleInversionPreference;
|
||||
|
||||
private int mLongPressTimeoutDefault;
|
||||
@@ -452,9 +458,11 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
|
||||
// Display color adjustments.
|
||||
mDisplayDaltonizerPreferenceScreen = findPreference(DISPLAY_DALTONIZER_PREFERENCE_SCREEN);
|
||||
|
||||
// Accessibility shortcut
|
||||
// Accessibility shortcut.
|
||||
mAccessibilityShortcutPreferenceScreen = findPreference(ACCESSIBILITY_SHORTCUT_PREFERENCE);
|
||||
|
||||
// Vibrations.
|
||||
mVibrationPreferenceScreen = findPreference(VIBRATION_PREFERENCE_SCREEN);
|
||||
}
|
||||
|
||||
private void updateAllPreferences() {
|
||||
@@ -661,6 +669,8 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
|
||||
mSelectLongPressTimeoutPreference.setValue(value);
|
||||
mSelectLongPressTimeoutPreference.setSummary(mLongPressTimeoutValueToTitleMap.get(value));
|
||||
|
||||
updateVibrationSummary(mVibrationPreferenceScreen);
|
||||
|
||||
updateFeatureSummary(Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED,
|
||||
mCaptioningPreferenceScreen);
|
||||
updateFeatureSummary(Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
|
||||
@@ -726,6 +736,29 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
|
||||
pref.setSummary(entries[index]);
|
||||
}
|
||||
|
||||
private void updateVibrationSummary(Preference pref) {
|
||||
Vibrator vibrator = getContext().getSystemService(Vibrator.class);
|
||||
final int intensity = Settings.System.getInt(getContext().getContentResolver(),
|
||||
Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
vibrator.getDefaultNotificationVibrationIntensity());
|
||||
mVibrationPreferenceScreen.setSummary(getVibrationSummary(getContext(), intensity));
|
||||
}
|
||||
|
||||
private String getVibrationSummary(Context context, @VibrationIntensity int intensity) {
|
||||
switch (intensity) {
|
||||
case Vibrator.VIBRATION_INTENSITY_OFF:
|
||||
return context.getString(R.string.accessibility_vibration_summary_off);
|
||||
case Vibrator.VIBRATION_INTENSITY_LOW:
|
||||
return context.getString(R.string.accessibility_vibration_summary_low);
|
||||
case Vibrator.VIBRATION_INTENSITY_MEDIUM:
|
||||
return context.getString(R.string.accessibility_vibration_summary_medium);
|
||||
case Vibrator.VIBRATION_INTENSITY_HIGH:
|
||||
return context.getString(R.string.accessibility_vibration_summary_high);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLockScreenRotationCheckbox() {
|
||||
Context context = getActivity();
|
||||
if (context != null) {
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.accessibility;
|
||||
|
||||
import android.os.Vibrator;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
|
||||
/**
|
||||
* Fragment for picking accessibility shortcut service
|
||||
*/
|
||||
public class NotificationVibrationPreferenceFragment extends VibrationPreferenceFragment {
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.ACCESSIBILITY_VIBRATION_NOTIFICATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.accessibility_notification_vibration_settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the setting string of the vibration intensity setting this preference is dealing with.
|
||||
*/
|
||||
@Override
|
||||
protected String getVibrationIntensitySetting() {
|
||||
return Settings.System.NOTIFICATION_VIBRATION_INTENSITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDefaultVibrationIntensity() {
|
||||
Vibrator vibrator = getContext().getSystemService(Vibrator.class);
|
||||
return vibrator.getDefaultNotificationVibrationIntensity();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.accessibility;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Vibrator;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
|
||||
/**
|
||||
* Fragment for picking accessibility shortcut service
|
||||
*/
|
||||
public class TouchVibrationPreferenceFragment extends VibrationPreferenceFragment {
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.ACCESSIBILITY_VIBRATION_TOUCH;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.accessibility_touch_vibration_settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the setting string of the vibration intensity setting this preference is dealing with.
|
||||
*/
|
||||
@Override
|
||||
protected String getVibrationIntensitySetting() {
|
||||
return Settings.System.HAPTIC_FEEDBACK_INTENSITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDefaultVibrationIntensity() {
|
||||
Vibrator vibrator = getContext().getSystemService(Vibrator.class);
|
||||
return vibrator.getDefaultHapticFeedbackIntensity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVibrationIntensitySelected(int intensity) {
|
||||
// We want to keep HAPTIC_FEEDBACK_ENABLED consistent with this setting since some
|
||||
// applications check it directly before triggering their own haptic feedback.
|
||||
final boolean hapticFeedbackEnabled = !(intensity == Vibrator.VIBRATION_INTENSITY_OFF);
|
||||
Settings.System.putInt(getContext().getContentResolver(),
|
||||
Settings.System.HAPTIC_FEEDBACK_ENABLED, hapticFeedbackEnabled ? 1 : 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.accessibility;
|
||||
|
||||
import static android.os.Vibrator.VibrationIntensity;
|
||||
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Vibrator;
|
||||
import android.provider.Settings;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.accessibility.AccessibilityShortcutController;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.widget.RadioButtonPickerFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Fragment for changing vibration settings.
|
||||
*/
|
||||
public abstract class VibrationPreferenceFragment extends RadioButtonPickerFragment {
|
||||
private static final String TAG = "VibrationPreferenceFragment";
|
||||
|
||||
@VisibleForTesting
|
||||
final static String KEY_INTENSITY_OFF = "intensity_off";
|
||||
@VisibleForTesting
|
||||
final static String KEY_INTENSITY_LOW = "intensity_low";
|
||||
@VisibleForTesting
|
||||
final static String KEY_INTENSITY_MEDIUM = "intensity_medium";
|
||||
@VisibleForTesting
|
||||
final static String KEY_INTENSITY_HIGH = "intensity_high";
|
||||
|
||||
private final Map<String, VibrationIntensityCandidateInfo> mCandidates;
|
||||
private final SettingsObserver mSettingsObserver;
|
||||
|
||||
public VibrationPreferenceFragment() {
|
||||
mCandidates = new ArrayMap<>();
|
||||
mCandidates.put(KEY_INTENSITY_OFF,
|
||||
new VibrationIntensityCandidateInfo(KEY_INTENSITY_OFF,
|
||||
R.string.accessibility_vibration_intensity_off,
|
||||
Vibrator.VIBRATION_INTENSITY_OFF));
|
||||
mCandidates.put(KEY_INTENSITY_LOW,
|
||||
new VibrationIntensityCandidateInfo(KEY_INTENSITY_LOW,
|
||||
R.string.accessibility_vibration_intensity_low,
|
||||
Vibrator.VIBRATION_INTENSITY_LOW));
|
||||
mCandidates.put(KEY_INTENSITY_MEDIUM,
|
||||
new VibrationIntensityCandidateInfo(KEY_INTENSITY_MEDIUM,
|
||||
R.string.accessibility_vibration_intensity_medium,
|
||||
Vibrator.VIBRATION_INTENSITY_MEDIUM));
|
||||
mCandidates.put(KEY_INTENSITY_HIGH,
|
||||
new VibrationIntensityCandidateInfo(KEY_INTENSITY_HIGH,
|
||||
R.string.accessibility_vibration_intensity_high,
|
||||
Vibrator.VIBRATION_INTENSITY_HIGH));
|
||||
mSettingsObserver = new SettingsObserver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
mSettingsObserver.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
mSettingsObserver.unregister();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the setting string of the vibration intensity setting this preference is dealing with.
|
||||
*/
|
||||
protected abstract String getVibrationIntensitySetting();
|
||||
|
||||
/**
|
||||
* Get the default intensity for the desired setting.
|
||||
*/
|
||||
protected abstract int getDefaultVibrationIntensity();
|
||||
|
||||
/**
|
||||
* When a new vibration intensity is selected by the user.
|
||||
*/
|
||||
protected void onVibrationIntensitySelected(int intensity) { }
|
||||
|
||||
@Override
|
||||
protected List<? extends CandidateInfo> getCandidates() {
|
||||
List<VibrationIntensityCandidateInfo> candidates = new ArrayList<>(mCandidates.values());
|
||||
candidates.sort(
|
||||
Comparator.comparing(VibrationIntensityCandidateInfo::getIntensity).reversed());
|
||||
return candidates;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultKey() {
|
||||
final int vibrationIntensity = Settings.System.getInt(getContext().getContentResolver(),
|
||||
getVibrationIntensitySetting(), getDefaultVibrationIntensity());
|
||||
for (VibrationIntensityCandidateInfo candidate : mCandidates.values()) {
|
||||
if (candidate.getIntensity() == vibrationIntensity) {
|
||||
return candidate.getKey();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setDefaultKey(String key) {
|
||||
VibrationIntensityCandidateInfo candidate = mCandidates.get(key);
|
||||
if (candidate == null) {
|
||||
Log.e(TAG, "Tried to set unknown intensity (key=" + key + ")!");
|
||||
return false;
|
||||
}
|
||||
Settings.System.putInt(getContext().getContentResolver(),
|
||||
getVibrationIntensitySetting(), candidate.getIntensity());
|
||||
onVibrationIntensitySelected(candidate.getIntensity());
|
||||
return true;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
class VibrationIntensityCandidateInfo extends CandidateInfo {
|
||||
private String mKey;
|
||||
private int mLabelId;
|
||||
@VibrationIntensity
|
||||
private int mIntensity;
|
||||
|
||||
public VibrationIntensityCandidateInfo(String key, int labelId, int intensity) {
|
||||
super(true /* enabled */);
|
||||
mKey = key;
|
||||
mLabelId = labelId;
|
||||
mIntensity = intensity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence loadLabel() {
|
||||
return getContext().getString(mLabelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable loadIcon() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return mKey;
|
||||
}
|
||||
|
||||
public int getIntensity() {
|
||||
return mIntensity;
|
||||
}
|
||||
}
|
||||
|
||||
private class SettingsObserver extends ContentObserver {
|
||||
public SettingsObserver() {
|
||||
super(new Handler());
|
||||
}
|
||||
|
||||
public void register() {
|
||||
getContext().getContentResolver().registerContentObserver(
|
||||
Settings.System.getUriFor(getVibrationIntensitySetting()), false, this);
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
getContext().getContentResolver().unregisterContentObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
updateCandidates();
|
||||
}
|
||||
}
|
||||
}
|
||||
153
src/com/android/settings/accessibility/VibrationSettings.java
Normal file
153
src/com/android/settings/accessibility/VibrationSettings.java
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.accessibility;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Vibrator;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.provider.Settings;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Activity with the accessibility settings.
|
||||
*/
|
||||
public class VibrationSettings extends SettingsPreferenceFragment implements Indexable {
|
||||
|
||||
// Preferences
|
||||
@VisibleForTesting
|
||||
static final String NOTIFICATION_VIBRATION_PREFERENCE_SCREEN =
|
||||
"notification_vibration_preference_screen";
|
||||
@VisibleForTesting
|
||||
static final String TOUCH_VIBRATION_PREFERENCE_SCREEN =
|
||||
"touch_vibration_preference_screen";
|
||||
|
||||
private final Handler mHandler = new Handler();
|
||||
private final SettingsContentObserver mSettingsContentObserver;
|
||||
|
||||
private Preference mNotificationVibrationPreferenceScreen;
|
||||
private Preference mTouchVibrationPreferenceScreen;
|
||||
|
||||
public VibrationSettings() {
|
||||
List<String> vibrationSettings = new ArrayList<>();
|
||||
vibrationSettings.add(Settings.System.HAPTIC_FEEDBACK_INTENSITY);
|
||||
vibrationSettings.add(Settings.System.NOTIFICATION_VIBRATION_INTENSITY);
|
||||
mSettingsContentObserver = new SettingsContentObserver(mHandler, vibrationSettings) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
updatePreferences();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.ACCESSIBILITY_VIBRATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
addPreferencesFromResource(R.xml.accessibility_vibration_settings);
|
||||
initializePreferences();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
updatePreferences();
|
||||
mSettingsContentObserver.register(getContentResolver());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mSettingsContentObserver.unregister(getContentResolver());
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
private void initializePreferences() {
|
||||
// Notification and notification vibration strength adjustments.
|
||||
mNotificationVibrationPreferenceScreen =
|
||||
findPreference(NOTIFICATION_VIBRATION_PREFERENCE_SCREEN);
|
||||
|
||||
// Touch feedback strength adjustments.
|
||||
mTouchVibrationPreferenceScreen = findPreference(TOUCH_VIBRATION_PREFERENCE_SCREEN);
|
||||
}
|
||||
|
||||
private void updatePreferences() {
|
||||
updateNotificationVibrationSummary(mNotificationVibrationPreferenceScreen);
|
||||
updateTouchVibrationSummary(mTouchVibrationPreferenceScreen);
|
||||
}
|
||||
|
||||
private void updateNotificationVibrationSummary(Preference pref) {
|
||||
Vibrator vibrator = getContext().getSystemService(Vibrator.class);
|
||||
final int intensity = Settings.System.getInt(getContext().getContentResolver(),
|
||||
Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
|
||||
vibrator.getDefaultNotificationVibrationIntensity());
|
||||
CharSequence summary = getVibrationIntensitySummary(getContext(), intensity);
|
||||
mNotificationVibrationPreferenceScreen.setSummary(summary);
|
||||
}
|
||||
|
||||
private void updateTouchVibrationSummary(Preference pref) {
|
||||
Vibrator vibrator = getContext().getSystemService(Vibrator.class);
|
||||
final int intensity = Settings.System.getInt(getContext().getContentResolver(),
|
||||
Settings.System.HAPTIC_FEEDBACK_INTENSITY,
|
||||
vibrator.getDefaultHapticFeedbackIntensity());
|
||||
CharSequence summary = getVibrationIntensitySummary(getContext(), intensity);
|
||||
mTouchVibrationPreferenceScreen.setSummary(summary);
|
||||
}
|
||||
|
||||
public static String getVibrationIntensitySummary(Context context, int intensity) {
|
||||
switch (intensity) {
|
||||
case Vibrator.VIBRATION_INTENSITY_OFF:
|
||||
return context.getString(R.string.accessibility_vibration_intensity_off);
|
||||
case Vibrator.VIBRATION_INTENSITY_LOW:
|
||||
return context.getString(R.string.accessibility_vibration_intensity_low);
|
||||
case Vibrator.VIBRATION_INTENSITY_MEDIUM:
|
||||
return context.getString(R.string.accessibility_vibration_intensity_medium);
|
||||
case Vibrator.VIBRATION_INTENSITY_HIGH:
|
||||
return context.getString(R.string.accessibility_vibration_intensity_high);
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
|
||||
boolean enabled) {
|
||||
List<SearchIndexableResource> indexables = new ArrayList<>();
|
||||
SearchIndexableResource indexable = new SearchIndexableResource(context);
|
||||
indexable.xmlResId = R.xml.accessibility_vibration_settings;
|
||||
indexables.add(indexable);
|
||||
return indexables;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -74,7 +74,7 @@ import com.android.settings.display.NightDisplaySettings;
|
||||
import com.android.settings.dream.DreamSettings;
|
||||
import com.android.settings.enterprise.EnterprisePrivacySettings;
|
||||
import com.android.settings.fuelgauge.AdvancedPowerUsageDetail;
|
||||
import com.android.settings.fuelgauge.BatterySaverSettings;
|
||||
import com.android.settings.fuelgauge.batterysaver.BatterySaverSettings;
|
||||
import com.android.settings.fuelgauge.PowerUsageSummary;
|
||||
import com.android.settings.fuelgauge.PowerUsageSummaryLegacy;
|
||||
import com.android.settings.gestures.AssistGestureSettings;
|
||||
|
||||
@@ -20,7 +20,7 @@ import android.os.PowerManager;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.fuelgauge.BatterySaverSettings;
|
||||
import com.android.settings.fuelgauge.batterysaver.BatterySaverSettings;
|
||||
|
||||
public class BatterySaverCondition extends Condition {
|
||||
public BatterySaverCondition(ConditionManager manager) {
|
||||
|
||||
@@ -23,12 +23,15 @@ import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Bundle;
|
||||
import android.service.settings.suggestions.Suggestion;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.TextUtils;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
@@ -117,7 +120,7 @@ public class SuggestionAdapter extends RecyclerView.Adapter<DashboardItemHolder>
|
||||
mConfig.setCardLayout(holder, suggestionCount, position);
|
||||
final Icon icon = suggestion.getIcon();
|
||||
final Drawable drawable = mCache.getIcon(icon);
|
||||
if ((suggestion.getFlags() & Suggestion.FLAG_ICON_TINTABLE) != 0) {
|
||||
if (drawable != null && (suggestion.getFlags() & Suggestion.FLAG_ICON_TINTABLE) != 0) {
|
||||
drawable.setTint(Utils.getColorAccent(mContext));
|
||||
}
|
||||
holder.icon.setImageDrawable(drawable);
|
||||
@@ -226,28 +229,27 @@ public class SuggestionAdapter extends RecyclerView.Adapter<DashboardItemHolder>
|
||||
return mSuggestions;
|
||||
}
|
||||
|
||||
private static class CardConfig {
|
||||
@VisibleForTesting
|
||||
static class CardConfig {
|
||||
// Card start/end margin
|
||||
private final int mMarginInner;
|
||||
private final int mMarginOuter;
|
||||
// Card width for different numbers of cards
|
||||
private final int mWidthSingleCard;
|
||||
private final int mWidthTwoCards;
|
||||
// Card width if there are more than 2 cards
|
||||
private final int mWidthMultipleCards;
|
||||
// padding between icon and title
|
||||
private final int mPaddingTitleTopSingleCard;
|
||||
private final int mPaddingTitleTopMultipleCards;
|
||||
private final WindowManager mWindowManager;
|
||||
|
||||
private static CardConfig sConfig;
|
||||
|
||||
private CardConfig(Context context) {
|
||||
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
final Resources res = context.getResources();
|
||||
mMarginInner =
|
||||
res.getDimensionPixelOffset(R.dimen.suggestion_card_inner_margin);
|
||||
mMarginOuter =
|
||||
res.getDimensionPixelOffset(R.dimen.suggestion_card_outer_margin);
|
||||
mWidthSingleCard = res.getDimensionPixelOffset(R.dimen.suggestion_card_width_one_card);
|
||||
mWidthTwoCards = res.getDimensionPixelOffset(R.dimen.suggestion_card_width_two_cards);
|
||||
mWidthMultipleCards =
|
||||
res.getDimensionPixelOffset(R.dimen.suggestion_card_width_multiple_cards);
|
||||
mPaddingTitleTopSingleCard =
|
||||
@@ -263,12 +265,12 @@ public class SuggestionAdapter extends RecyclerView.Adapter<DashboardItemHolder>
|
||||
return sConfig;
|
||||
}
|
||||
|
||||
private void setCardLayout(DashboardItemHolder holder, int suggestionCount,
|
||||
int position) {
|
||||
@VisibleForTesting
|
||||
void setCardLayout(DashboardItemHolder holder, int suggestionCount, int position) {
|
||||
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||
suggestionCount == 1
|
||||
? mWidthSingleCard : suggestionCount == 2
|
||||
? mWidthTwoCards : mWidthMultipleCards,
|
||||
? LinearLayout.LayoutParams.MATCH_PARENT : suggestionCount == 2
|
||||
? getWidthForTwoCrads() : mWidthMultipleCards,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
if (suggestionCount == 1) {
|
||||
params.setMarginStart(mMarginOuter);
|
||||
@@ -281,6 +283,16 @@ public class SuggestionAdapter extends RecyclerView.Adapter<DashboardItemHolder>
|
||||
holder.itemView.setLayoutParams(params);
|
||||
}
|
||||
|
||||
private int getWidthForTwoCrads() {
|
||||
return (getScreenWidth() - mMarginInner - mMarginOuter * 2) / 2;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
int getScreenWidth() {
|
||||
final DisplayMetrics metrics = new DisplayMetrics();
|
||||
mWindowManager.getDefaultDisplay().getMetrics(metrics);
|
||||
return metrics.widthPixels;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,253 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.fuelgauge;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.Global;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.util.Log;
|
||||
import android.widget.Switch;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.dashboard.conditional.BatterySaverCondition;
|
||||
import com.android.settings.dashboard.conditional.ConditionManager;
|
||||
import com.android.settings.notification.SettingPref;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class BatterySaverSettings extends SettingsPreferenceFragment
|
||||
implements SwitchBar.OnSwitchChangeListener, BatterySaverReceiver.BatterySaverListener,
|
||||
Indexable {
|
||||
private static final String TAG = "BatterySaverSettings";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
private static final String KEY_TURN_ON_AUTOMATICALLY = "turn_on_automatically";
|
||||
private static final long WAIT_FOR_SWITCH_ANIM = 500;
|
||||
|
||||
private final Handler mHandler = new Handler();
|
||||
private final SettingsObserver mSettingsObserver = new SettingsObserver(mHandler);
|
||||
|
||||
@VisibleForTesting
|
||||
SwitchBar mSwitchBar;
|
||||
private Context mContext;
|
||||
private boolean mCreated;
|
||||
private SettingPref mTriggerPref;
|
||||
private Switch mSwitch;
|
||||
private boolean mValidListener;
|
||||
private PowerManager mPowerManager;
|
||||
private BatterySaverReceiver mReceiver;
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.FUELGAUGE_BATTERY_SAVER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
if (mCreated) {
|
||||
mSwitchBar.show();
|
||||
return;
|
||||
}
|
||||
mCreated = true;
|
||||
addPreferencesFromResource(R.xml.battery_saver_settings);
|
||||
mFooterPreferenceMixin.createFooterPreference()
|
||||
.setTitle(com.android.internal.R.string.battery_saver_description);
|
||||
mContext = getActivity();
|
||||
mSwitchBar = ((SettingsActivity) mContext).getSwitchBar();
|
||||
mSwitchBar.setSwitchBarText(R.string.battery_saver_master_switch_title,
|
||||
R.string.battery_saver_master_switch_title);
|
||||
mSwitch = mSwitchBar.getSwitch();
|
||||
mSwitchBar.show();
|
||||
|
||||
int[] levelChoices = getResources().getIntArray(R.array.battery_saver_trigger_values);
|
||||
final int currentThreshold = Global.getInt(mContext.getContentResolver(),
|
||||
Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
|
||||
levelChoices = ArrayUtils.appendInt(levelChoices, currentThreshold);
|
||||
Arrays.sort(levelChoices);
|
||||
|
||||
mTriggerPref = new SettingPref(SettingPref.TYPE_GLOBAL, KEY_TURN_ON_AUTOMATICALLY,
|
||||
Global.LOW_POWER_MODE_TRIGGER_LEVEL,
|
||||
0, /*default*/
|
||||
levelChoices) {
|
||||
@Override
|
||||
protected String getCaption(Resources res, int value) {
|
||||
if (value > 0 && value <= 100) {
|
||||
return res.getString(R.string.battery_saver_turn_on_automatically_pct,
|
||||
Utils.formatPercentage(value));
|
||||
}
|
||||
return res.getString(R.string.battery_saver_turn_on_automatically_never);
|
||||
}
|
||||
};
|
||||
mTriggerPref.init(this);
|
||||
|
||||
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
|
||||
mReceiver = new BatterySaverReceiver(mContext);
|
||||
mReceiver.setBatterySaverListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
mSwitchBar.hide();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mSettingsObserver.setListening(true);
|
||||
mReceiver.setListening(true);
|
||||
if (!mValidListener) {
|
||||
mSwitchBar.addOnSwitchChangeListener(this);
|
||||
mValidListener = true;
|
||||
}
|
||||
updateSwitch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mSettingsObserver.setListening(false);
|
||||
mReceiver.setListening(false);
|
||||
if (mValidListener) {
|
||||
mSwitchBar.removeOnSwitchChangeListener(this);
|
||||
mValidListener = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwitchChanged(Switch switchView, boolean isChecked) {
|
||||
mHandler.removeCallbacks(mStartMode);
|
||||
if (isChecked) {
|
||||
mHandler.postDelayed(mStartMode, WAIT_FOR_SWITCH_ANIM);
|
||||
} else {
|
||||
if (DEBUG) Log.d(TAG, "Stopping low power mode from settings");
|
||||
trySetPowerSaveMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void trySetPowerSaveMode(boolean mode) {
|
||||
if (!mPowerManager.setPowerSaveMode(mode)) {
|
||||
if (DEBUG) Log.d(TAG, "Setting mode failed, fallback to current value");
|
||||
mHandler.post(mUpdateSwitch);
|
||||
}
|
||||
// TODO: Remove once broadcast is in place.
|
||||
ConditionManager.get(getContext()).getCondition(BatterySaverCondition.class).refreshState();
|
||||
}
|
||||
|
||||
private void updateSwitch() {
|
||||
final boolean mode = mPowerManager.isPowerSaveMode();
|
||||
if (DEBUG) Log.d(TAG, "updateSwitch: isChecked=" + mSwitch.isChecked() + " mode=" + mode);
|
||||
if (mode == mSwitch.isChecked()) return;
|
||||
|
||||
// set listener to null so that that code below doesn't trigger onCheckedChanged()
|
||||
if (mValidListener) {
|
||||
mSwitchBar.removeOnSwitchChangeListener(this);
|
||||
}
|
||||
mSwitch.setChecked(mode);
|
||||
if (mValidListener) {
|
||||
mSwitchBar.addOnSwitchChangeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
private final Runnable mUpdateSwitch = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateSwitch();
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mStartMode = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
AsyncTask.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (DEBUG) Log.d(TAG, "Starting low power mode from settings");
|
||||
trySetPowerSaveMode(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onPowerSaveModeChanged() {
|
||||
mHandler.post(mUpdateSwitch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBatteryChanged(boolean pluggedIn) {
|
||||
mSwitchBar.setEnabled(!pluggedIn);
|
||||
}
|
||||
|
||||
private final class SettingsObserver extends ContentObserver {
|
||||
private final Uri LOW_POWER_MODE_TRIGGER_LEVEL_URI
|
||||
= Global.getUriFor(Global.LOW_POWER_MODE_TRIGGER_LEVEL);
|
||||
|
||||
public SettingsObserver(Handler handler) {
|
||||
super(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
if (LOW_POWER_MODE_TRIGGER_LEVEL_URI.equals(uri)) {
|
||||
mTriggerPref.update(mContext);
|
||||
}
|
||||
}
|
||||
|
||||
public void setListening(boolean listening) {
|
||||
final ContentResolver cr = getContentResolver();
|
||||
if (listening) {
|
||||
cr.registerContentObserver(LOW_POWER_MODE_TRIGGER_LEVEL_URI, false, this);
|
||||
} else {
|
||||
cr.unregisterContentObserver(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For Search.
|
||||
*/
|
||||
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(
|
||||
Context context, boolean enabled) {
|
||||
final SearchIndexableResource sir = new SearchIndexableResource(context);
|
||||
sir.xmlResId = R.xml.battery_saver_settings;
|
||||
return Arrays.asList(sir);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -72,7 +72,7 @@ import java.util.List;
|
||||
* consumed since the last time it was unplugged.
|
||||
*/
|
||||
public class PowerUsageSummary extends PowerUsageBase implements OnLongClickListener,
|
||||
OnClickListener, BatteryTipPreferenceController.BatteryTipListener {
|
||||
BatteryTipPreferenceController.BatteryTipListener {
|
||||
|
||||
static final String TAG = "PowerUsageSummary";
|
||||
|
||||
@@ -80,7 +80,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
|
||||
private static final String KEY_APP_LIST = "app_list";
|
||||
private static final String KEY_BATTERY_HEADER = "battery_header";
|
||||
private static final String KEY_BATTERY_TIP = "battery_tip";
|
||||
private static final String KEY_SHOW_ALL_APPS = "show_all_apps";
|
||||
|
||||
private static final String KEY_SCREEN_USAGE = "screen_usage";
|
||||
private static final String KEY_TIME_SINCE_LAST_FULL_CHARGE = "last_full_charge";
|
||||
@@ -224,15 +223,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
|
||||
return MetricsEvent.FUELGAUGE_POWER_USAGE_SUMMARY_V2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(Preference preference) {
|
||||
if (KEY_BATTERY_HEADER.equals(preference.getKey())) {
|
||||
performBatteryHeaderClick();
|
||||
return true;
|
||||
}
|
||||
return super.onPreferenceTreeClick(preference);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
@@ -311,22 +301,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
|
||||
}
|
||||
}
|
||||
|
||||
private void performBatteryHeaderClick() {
|
||||
if (mPowerFeatureProvider.isAdvancedUiEnabled()) {
|
||||
Utils.startWithFragment(getContext(), PowerUsageAdvanced.class.getName(), null,
|
||||
null, 0, R.string.advanced_battery_title, null, getMetricsCategory());
|
||||
} else {
|
||||
mStatsHelper.storeStatsHistoryInFile(BatteryHistoryDetail.BATTERY_HISTORY_FILE);
|
||||
Bundle args = new Bundle(2);
|
||||
args.putString(BatteryHistoryDetail.EXTRA_STATS,
|
||||
BatteryHistoryDetail.BATTERY_HISTORY_FILE);
|
||||
args.putParcelable(BatteryHistoryDetail.EXTRA_BROADCAST,
|
||||
mStatsHelper.getBatteryBroadcast());
|
||||
Utils.startWithFragment(getContext(), BatteryHistoryDetail.class.getName(), args,
|
||||
null, 0, R.string.history_details_title, null, getMetricsCategory());
|
||||
}
|
||||
}
|
||||
|
||||
protected void refreshUi() {
|
||||
final Context context = getContext();
|
||||
if (context == null) {
|
||||
@@ -405,12 +379,9 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
|
||||
getLoaderManager().restartLoader(BATTERY_INFO_LOADER, Bundle.EMPTY,
|
||||
mBatteryInfoLoaderCallbacks);
|
||||
if (mPowerFeatureProvider.isEstimateDebugEnabled()) {
|
||||
// Unfortunately setting a long click listener on a view means it will no
|
||||
// longer pass the regular click event to the parent, so we have to register
|
||||
// a regular click listener as well.
|
||||
// Set long click action for summary to show debug info
|
||||
View header = mBatteryLayoutPref.findViewById(R.id.summary1);
|
||||
header.setOnLongClickListener(this);
|
||||
header.setOnClickListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,11 +392,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
performBatteryHeaderClick();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void restartBatteryStatsLoader() {
|
||||
restartBatteryStatsLoader(true /* clearHeader */);
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.fuelgauge.batterysaver;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v14.preference.SwitchPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.core.TogglePreferenceController;
|
||||
|
||||
/**
|
||||
* Controller that update whether to turn on battery saver automatically
|
||||
*/
|
||||
public class AutoBatterySaverPreferenceController extends TogglePreferenceController implements
|
||||
Preference.OnPreferenceChangeListener {
|
||||
private static final int LOW_POWER_MODE_TRIGGER_THRESHOLD = 15;
|
||||
|
||||
@VisibleForTesting
|
||||
static final String KEY_AUTO_BATTERY_SAVER = "auto_battery_saver";
|
||||
|
||||
public AutoBatterySaverPreferenceController(Context context) {
|
||||
super(context, KEY_AUTO_BATTERY_SAVER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setChecked(boolean isChecked) {
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL,
|
||||
isChecked
|
||||
? LOW_POWER_MODE_TRIGGER_THRESHOLD
|
||||
: 0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.fuelgauge.batterysaver;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.widget.SeekBarPreference;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||
|
||||
/**
|
||||
* Controller that update the battery saver seekbar
|
||||
*/
|
||||
public class AutoBatterySeekBarPreferenceController extends BasePreferenceController implements
|
||||
LifecycleObserver, OnStart, OnStop, SeekBarPreference.OnPreferenceChangeListener {
|
||||
@VisibleForTesting
|
||||
static final String KEY_AUTO_BATTERY_SEEK_BAR = "battery_saver_seek_bar";
|
||||
private SeekBarPreference mPreference;
|
||||
private AutoBatterySaverSettingObserver mContentObserver;
|
||||
|
||||
public AutoBatterySeekBarPreferenceController(Context context, Lifecycle lifecycle) {
|
||||
super(context, KEY_AUTO_BATTERY_SEEK_BAR);
|
||||
mContentObserver = new AutoBatterySaverSettingObserver(new Handler());
|
||||
if (lifecycle != null) {
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mPreference = (SeekBarPreference) screen.findPreference(
|
||||
KEY_AUTO_BATTERY_SEEK_BAR);
|
||||
updatePreference(mPreference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
updatePreference(preference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
mContentObserver.registerContentObserver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
mContentObserver.unRegisterContentObserver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
final int progress = (int) newValue;
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, progress);
|
||||
return true;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void updatePreference(Preference preference) {
|
||||
final ContentResolver contentResolver = mContext.getContentResolver();
|
||||
final int level = Settings.Global.getInt(contentResolver,
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
|
||||
if (level == 0) {
|
||||
preference.setVisible(false);
|
||||
} else {
|
||||
preference.setVisible(true);
|
||||
preference.setTitle(mContext.getString(R.string.battery_saver_seekbar_title,
|
||||
Utils.formatPercentage(level)));
|
||||
((SeekBarPreference) preference).setProgress(level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Observer that listens to change from {@link Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL}
|
||||
*/
|
||||
private final class AutoBatterySaverSettingObserver extends ContentObserver {
|
||||
private final Uri mUri = Settings.Global.getUriFor(
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL);
|
||||
private final ContentResolver mContentResolver;
|
||||
|
||||
public AutoBatterySaverSettingObserver(Handler handler) {
|
||||
super(handler);
|
||||
mContentResolver = mContext.getContentResolver();
|
||||
}
|
||||
|
||||
public void registerContentObserver() {
|
||||
mContentResolver.registerContentObserver(mUri, false, this);
|
||||
}
|
||||
|
||||
public void unRegisterContentObserver() {
|
||||
mContentResolver.unregisterContentObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri, int userId) {
|
||||
if (mUri.equals(uri)) {
|
||||
updatePreference(mPreference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.settings.fuelgauge.batterysaver;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.PowerManager;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.provider.Settings.Global;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Battery saver settings page
|
||||
*/
|
||||
public class BatterySaverSettings extends DashboardFragment {
|
||||
private static final String TAG = "BatterySaverSettings";
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.FUELGAUGE_BATTERY_SAVER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.battery_saver_settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
return buildPreferenceControllers(context, getLifecycle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHelpResource() {
|
||||
return R.string.help_url_battery_saver_settings;
|
||||
}
|
||||
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(
|
||||
Context context, Lifecycle lifecycle) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new AutoBatterySaverPreferenceController(context));
|
||||
controllers.add(new AutoBatterySeekBarPreferenceController(context, lifecycle));
|
||||
return controllers;
|
||||
}
|
||||
|
||||
/**
|
||||
* For Search.
|
||||
*/
|
||||
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(
|
||||
Context context, boolean enabled) {
|
||||
final SearchIndexableResource sir = new SearchIndexableResource(context);
|
||||
sir.xmlResId = R.xml.battery_saver_settings;
|
||||
return Arrays.asList(sir);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
return buildPreferenceControllers(context, null);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -19,10 +19,8 @@ package com.android.settings.notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationChannelGroup;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.support.v14.preference.SwitchPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceCategory;
|
||||
import android.support.v7.preference.PreferenceGroup;
|
||||
@@ -32,9 +30,8 @@ import android.util.Log;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.AppInfoBase;
|
||||
import com.android.settings.widget.MasterSwitchPreference;
|
||||
import com.android.settings.widget.MasterCheckBoxPreference;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -179,17 +176,37 @@ public class AppNotificationSettings extends NotificationSettingsBase {
|
||||
groupCategory.setKey(group.getId());
|
||||
populateGroupToggle(groupCategory, group);
|
||||
}
|
||||
|
||||
final List<NotificationChannel> channels = group.getChannels();
|
||||
Collections.sort(channels, mChannelComparator);
|
||||
int N = channels.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
final NotificationChannel channel = channels.get(i);
|
||||
populateSingleChannelPrefs(groupCategory, channel, group.isBlocked());
|
||||
if (!group.isBlocked()) {
|
||||
final List<NotificationChannel> channels = group.getChannels();
|
||||
Collections.sort(channels, mChannelComparator);
|
||||
int N = channels.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
final NotificationChannel channel = channels.get(i);
|
||||
populateSingleChannelPrefs(groupCategory, channel, group.isBlocked());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void populateGroupToggle(final PreferenceGroup parent,
|
||||
NotificationChannelGroup group) {
|
||||
RestrictedSwitchPreference preference = new RestrictedSwitchPreference(getPrefContext());
|
||||
preference.setTitle(R.string.notification_switch_label);
|
||||
preference.setEnabled(mSuspendedAppsAdmin == null
|
||||
&& isChannelGroupBlockable(group));
|
||||
preference.setChecked(!group.isBlocked());
|
||||
preference.setOnPreferenceClickListener(preference1 -> {
|
||||
final boolean allowGroup = ((SwitchPreference) preference1).isChecked();
|
||||
group.setBlocked(!allowGroup);
|
||||
mBackend.updateChannelGroup(mAppRow.pkg, mAppRow.uid, group);
|
||||
|
||||
onGroupBlockStateChanged(group);
|
||||
return true;
|
||||
});
|
||||
|
||||
parent.addPreference(preference);
|
||||
}
|
||||
|
||||
private Comparator<NotificationChannelGroup> mChannelGroupComparator =
|
||||
new Comparator<NotificationChannelGroup>() {
|
||||
|
||||
@@ -204,4 +221,37 @@ public class AppNotificationSettings extends NotificationSettingsBase {
|
||||
return left.getId().compareTo(right.getId());
|
||||
}
|
||||
};
|
||||
|
||||
protected void onGroupBlockStateChanged(NotificationChannelGroup group) {
|
||||
if (group == null) {
|
||||
return;
|
||||
}
|
||||
PreferenceGroup groupGroup = (
|
||||
PreferenceGroup) getPreferenceScreen().findPreference(group.getId());
|
||||
|
||||
if (groupGroup != null) {
|
||||
if (group.isBlocked()) {
|
||||
List<Preference> toRemove = new ArrayList<>();
|
||||
int childCount = groupGroup.getPreferenceCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
Preference pref = groupGroup.getPreference(i);
|
||||
if (pref instanceof MasterCheckBoxPreference) {
|
||||
toRemove.add(pref);
|
||||
}
|
||||
}
|
||||
for (Preference pref : toRemove) {
|
||||
groupGroup.removePreference(pref);
|
||||
}
|
||||
} else {
|
||||
final List<NotificationChannel> channels = group.getChannels();
|
||||
Collections.sort(channels, mChannelComparator);
|
||||
int N = channels.size();
|
||||
for (int i = 0; i < N; i++) {
|
||||
final NotificationChannel channel = channels.get(i);
|
||||
populateSingleChannelPrefs(groupGroup, channel, group.isBlocked());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -103,6 +103,10 @@ public class BlockPreferenceController extends NotificationPreferenceController
|
||||
mChannel.setImportance(importance);
|
||||
saveChannel();
|
||||
}
|
||||
if (mBackend.onlyHasDefaultChannel(mAppRow.pkg, mAppRow.uid)) {
|
||||
mAppRow.banned = blocked;
|
||||
mBackend.setNotificationsEnabledForPackage(mAppRow.pkg, mAppRow.uid, !blocked);
|
||||
}
|
||||
} else if (mChannelGroup != null && mChannelGroup.getGroup() != null) {
|
||||
mChannelGroup.setBlocked(blocked);
|
||||
mBackend.updateChannelGroup(mAppRow.pkg, mAppRow.uid, mChannelGroup.getGroup());
|
||||
|
||||
@@ -1,467 +0,0 @@
|
||||
package com.android.settings.notification;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
import static android.util.Log.wtf;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.Condition;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Objects;
|
||||
|
||||
public class EnableZenModeDialog extends InstrumentedDialogFragment {
|
||||
|
||||
private static final String TAG = "EnableZenModeDialog";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
private static final int[] MINUTE_BUCKETS = ZenModeConfig.MINUTE_BUCKETS;
|
||||
private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
|
||||
private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
|
||||
private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
|
||||
|
||||
@VisibleForTesting
|
||||
public static final int FOREVER_CONDITION_INDEX = 0;
|
||||
@VisibleForTesting
|
||||
public static final int COUNTDOWN_CONDITION_INDEX = 1;
|
||||
@VisibleForTesting
|
||||
public static final int COUNTDOWN_ALARM_CONDITION_INDEX = 2;
|
||||
@VisibleForTesting
|
||||
protected Activity mActivity;
|
||||
|
||||
private static final int SECONDS_MS = 1000;
|
||||
private static final int MINUTES_MS = 60 * SECONDS_MS;
|
||||
|
||||
@VisibleForTesting
|
||||
protected Uri mForeverId;
|
||||
private int mBucketIndex = -1;
|
||||
|
||||
private AlarmManager mAlarmManager;
|
||||
private int mUserId;
|
||||
private boolean mAttached;
|
||||
|
||||
@VisibleForTesting
|
||||
protected Context mContext;
|
||||
|
||||
private RadioGroup mZenRadioGroup;
|
||||
@VisibleForTesting
|
||||
protected LinearLayout mZenRadioGroupContent;
|
||||
private int MAX_MANUAL_DND_OPTIONS = 3;
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
NotificationManager noMan = (NotificationManager) getContext().
|
||||
getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
mContext = getContext();
|
||||
mForeverId = Condition.newId(mContext).appendPath("forever").build();
|
||||
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
|
||||
mUserId = mContext.getUserId();
|
||||
mAttached = false;
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(getContext())
|
||||
.setTitle(R.string.zen_mode_settings_turn_on_dialog_title)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(R.string.zen_mode_enable_dialog_turn_on,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
int checkedId = mZenRadioGroup.getCheckedRadioButtonId();
|
||||
ConditionTag tag = getConditionTagAt(checkedId);
|
||||
|
||||
if (isForever(tag.condition)) {
|
||||
MetricsLogger.action(getContext(),
|
||||
MetricsProto.MetricsEvent.
|
||||
NOTIFICATION_ZEN_MODE_TOGGLE_ON_FOREVER);
|
||||
} else if (isAlarm(tag.condition)) {
|
||||
MetricsLogger.action(getContext(),
|
||||
MetricsProto.MetricsEvent.
|
||||
NOTIFICATION_ZEN_MODE_TOGGLE_ON_ALARM);
|
||||
} else if (isCountdown(tag.condition)) {
|
||||
MetricsLogger.action(getContext(),
|
||||
MetricsProto.MetricsEvent.
|
||||
NOTIFICATION_ZEN_MODE_TOGGLE_ON_COUNTDOWN);
|
||||
} else {
|
||||
wtf(TAG, "Invalid manual condition: " + tag.condition);
|
||||
}
|
||||
// always triggers priority-only dnd with chosen condition
|
||||
noMan.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
|
||||
getRealConditionId(tag.condition), TAG);
|
||||
}
|
||||
});
|
||||
|
||||
View contentView = getContentView();
|
||||
bindConditions(forever());
|
||||
builder.setView(contentView);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
private void hideAllConditions() {
|
||||
final int N = mZenRadioGroupContent.getChildCount();
|
||||
for (int i = 0; i < N; i++) {
|
||||
mZenRadioGroupContent.getChildAt(i).setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
protected View getContentView() {
|
||||
if (mActivity == null) {
|
||||
mActivity = getActivity();
|
||||
}
|
||||
final LayoutInflater inflater = mActivity.getLayoutInflater();
|
||||
View contentView = inflater.inflate(R.layout.zen_mode_turn_on_dialog_container, null);
|
||||
ScrollView container = (ScrollView) contentView.findViewById(R.id.container);
|
||||
|
||||
mZenRadioGroup = container.findViewById(R.id.zen_radio_buttons);
|
||||
mZenRadioGroupContent = container.findViewById(R.id.zen_radio_buttons_content);
|
||||
|
||||
for (int i = 0; i < MAX_MANUAL_DND_OPTIONS; i++) {
|
||||
final View radioButton = inflater.inflate(R.layout.zen_mode_radio_button,
|
||||
mZenRadioGroup, false);
|
||||
mZenRadioGroup.addView(radioButton);
|
||||
radioButton.setId(i);
|
||||
|
||||
final View radioButtonContent = inflater.inflate(R.layout.zen_mode_condition,
|
||||
mZenRadioGroupContent, false);
|
||||
radioButtonContent.setId(i + MAX_MANUAL_DND_OPTIONS);
|
||||
mZenRadioGroupContent.addView(radioButtonContent);
|
||||
}
|
||||
hideAllConditions();
|
||||
return contentView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.NOTIFICATION_ZEN_MODE_ENABLE_DIALOG;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected void bind(final Condition condition, final View row, final int rowId) {
|
||||
if (condition == null) throw new IllegalArgumentException("condition must not be null");
|
||||
final boolean enabled = condition.state == Condition.STATE_TRUE;
|
||||
final ConditionTag tag = row.getTag() != null ? (ConditionTag) row.getTag() :
|
||||
new ConditionTag();
|
||||
row.setTag(tag);
|
||||
final boolean first = tag.rb == null;
|
||||
if (tag.rb == null) {
|
||||
tag.rb = (RadioButton) mZenRadioGroup.getChildAt(rowId);
|
||||
}
|
||||
tag.condition = condition;
|
||||
final Uri conditionId = getConditionId(tag.condition);
|
||||
if (DEBUG) Log.d(TAG, "bind i=" + mZenRadioGroupContent.indexOfChild(row) + " first="
|
||||
+ first + " condition=" + conditionId);
|
||||
tag.rb.setEnabled(enabled);
|
||||
tag.rb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
if (isChecked) {
|
||||
tag.rb.setChecked(true);
|
||||
if (DEBUG) Log.d(TAG, "onCheckedChanged " + conditionId);
|
||||
MetricsLogger.action(mContext,
|
||||
MetricsProto.MetricsEvent.QS_DND_CONDITION_SELECT);
|
||||
announceConditionSelection(tag);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
updateUi(tag, row, condition, enabled, rowId, conditionId);
|
||||
row.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected ConditionTag getConditionTagAt(int index) {
|
||||
return (ConditionTag) mZenRadioGroupContent.getChildAt(index).getTag();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected void bindConditions(Condition c) {
|
||||
// forever
|
||||
bind(forever(), mZenRadioGroupContent.getChildAt(FOREVER_CONDITION_INDEX),
|
||||
FOREVER_CONDITION_INDEX);
|
||||
if (c == null) {
|
||||
bindGenericCountdown();
|
||||
bindNextAlarm(getTimeUntilNextAlarmCondition());
|
||||
} else if (isForever(c)) {
|
||||
getConditionTagAt(FOREVER_CONDITION_INDEX).rb.setChecked(true);
|
||||
bindGenericCountdown();
|
||||
bindNextAlarm(getTimeUntilNextAlarmCondition());
|
||||
} else {
|
||||
if (isAlarm(c)) {
|
||||
bindGenericCountdown();
|
||||
bindNextAlarm(c);
|
||||
getConditionTagAt(COUNTDOWN_ALARM_CONDITION_INDEX).rb.setChecked(true);
|
||||
} else if (isCountdown(c)) {
|
||||
bindNextAlarm(getTimeUntilNextAlarmCondition());
|
||||
bind(c, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
|
||||
COUNTDOWN_CONDITION_INDEX);
|
||||
getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);
|
||||
} else {
|
||||
wtf(TAG, "Invalid manual condition: " + c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Uri getConditionId(Condition condition) {
|
||||
return condition != null ? condition.id : null;
|
||||
}
|
||||
|
||||
public Condition forever() {
|
||||
Uri foreverId = Condition.newId(mContext).appendPath("forever").build();
|
||||
return new Condition(foreverId, foreverSummary(mContext), "", "", 0 /*icon*/,
|
||||
Condition.STATE_TRUE, 0 /*flags*/);
|
||||
}
|
||||
|
||||
public long getNextAlarm() {
|
||||
final AlarmManager.AlarmClockInfo info = mAlarmManager.getNextAlarmClock(mUserId);
|
||||
return info != null ? info.getTriggerTime() : 0;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected boolean isAlarm(Condition c) {
|
||||
return c != null && ZenModeConfig.isValidCountdownToAlarmConditionId(c.id);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected boolean isCountdown(Condition c) {
|
||||
return c != null && ZenModeConfig.isValidCountdownConditionId(c.id);
|
||||
}
|
||||
|
||||
private boolean isForever(Condition c) {
|
||||
return c != null && mForeverId.equals(c.id);
|
||||
}
|
||||
|
||||
private Uri getRealConditionId(Condition condition) {
|
||||
return isForever(condition) ? null : getConditionId(condition);
|
||||
}
|
||||
|
||||
private String foreverSummary(Context context) {
|
||||
return context.getString(com.android.internal.R.string.zen_mode_forever);
|
||||
}
|
||||
|
||||
private static void setToMidnight(Calendar calendar) {
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
}
|
||||
|
||||
// Returns a time condition if the next alarm is within the next week.
|
||||
@VisibleForTesting
|
||||
protected Condition getTimeUntilNextAlarmCondition() {
|
||||
GregorianCalendar weekRange = new GregorianCalendar();
|
||||
setToMidnight(weekRange);
|
||||
weekRange.add(Calendar.DATE, 6);
|
||||
final long nextAlarmMs = getNextAlarm();
|
||||
if (nextAlarmMs > 0) {
|
||||
GregorianCalendar nextAlarm = new GregorianCalendar();
|
||||
nextAlarm.setTimeInMillis(nextAlarmMs);
|
||||
setToMidnight(nextAlarm);
|
||||
|
||||
if (weekRange.compareTo(nextAlarm) >= 0) {
|
||||
return ZenModeConfig.toNextAlarmCondition(mContext, nextAlarmMs,
|
||||
ActivityManager.getCurrentUser());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected void bindGenericCountdown() {
|
||||
mBucketIndex = DEFAULT_BUCKET_INDEX;
|
||||
Condition countdown = ZenModeConfig.toTimeCondition(mContext,
|
||||
MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
|
||||
if (!mAttached || getConditionTagAt(COUNTDOWN_CONDITION_INDEX).condition == null) {
|
||||
bind(countdown, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
|
||||
COUNTDOWN_CONDITION_INDEX);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateUi(ConditionTag tag, View row, Condition condition,
|
||||
boolean enabled, int rowId, Uri conditionId) {
|
||||
if (tag.lines == null) {
|
||||
tag.lines = row.findViewById(android.R.id.content);
|
||||
}
|
||||
if (tag.line1 == null) {
|
||||
tag.line1 = (TextView) row.findViewById(android.R.id.text1);
|
||||
}
|
||||
|
||||
if (tag.line2 == null) {
|
||||
tag.line2 = (TextView) row.findViewById(android.R.id.text2);
|
||||
}
|
||||
|
||||
final String line1 = !TextUtils.isEmpty(condition.line1) ? condition.line1
|
||||
: condition.summary;
|
||||
final String line2 = condition.line2;
|
||||
tag.line1.setText(line1);
|
||||
if (TextUtils.isEmpty(line2)) {
|
||||
tag.line2.setVisibility(View.GONE);
|
||||
} else {
|
||||
tag.line2.setVisibility(View.VISIBLE);
|
||||
tag.line2.setText(line2);
|
||||
}
|
||||
tag.lines.setEnabled(enabled);
|
||||
tag.lines.setAlpha(enabled ? 1 : .4f);
|
||||
|
||||
tag.lines.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
tag.rb.setChecked(true);
|
||||
}
|
||||
});
|
||||
|
||||
// minus button
|
||||
final ImageView button1 = (ImageView) row.findViewById(android.R.id.button1);
|
||||
button1.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
onClickTimeButton(row, tag, false /*down*/, rowId);
|
||||
}
|
||||
});
|
||||
|
||||
// plus button
|
||||
final ImageView button2 = (ImageView) row.findViewById(android.R.id.button2);
|
||||
button2.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
onClickTimeButton(row, tag, true /*up*/, rowId);
|
||||
}
|
||||
});
|
||||
|
||||
final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
|
||||
if (rowId == COUNTDOWN_CONDITION_INDEX && time > 0) {
|
||||
button1.setVisibility(View.VISIBLE);
|
||||
button2.setVisibility(View.VISIBLE);
|
||||
if (mBucketIndex > -1) {
|
||||
button1.setEnabled(mBucketIndex > 0);
|
||||
button2.setEnabled(mBucketIndex < MINUTE_BUCKETS.length - 1);
|
||||
} else {
|
||||
final long span = time - System.currentTimeMillis();
|
||||
button1.setEnabled(span > MIN_BUCKET_MINUTES * MINUTES_MS);
|
||||
final Condition maxCondition = ZenModeConfig.toTimeCondition(mContext,
|
||||
MAX_BUCKET_MINUTES, ActivityManager.getCurrentUser());
|
||||
button2.setEnabled(!Objects.equals(condition.summary, maxCondition.summary));
|
||||
}
|
||||
|
||||
button1.setAlpha(button1.isEnabled() ? 1f : .5f);
|
||||
button2.setAlpha(button2.isEnabled() ? 1f : .5f);
|
||||
} else {
|
||||
button1.setVisibility(View.GONE);
|
||||
button2.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected void bindNextAlarm(Condition c) {
|
||||
View alarmContent = mZenRadioGroupContent.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX);
|
||||
ConditionTag tag = (ConditionTag) alarmContent.getTag();
|
||||
|
||||
if (c != null && (!mAttached || tag == null || tag.condition == null)) {
|
||||
bind(c, alarmContent, COUNTDOWN_ALARM_CONDITION_INDEX);
|
||||
}
|
||||
|
||||
// hide the alarm radio button if there isn't a "next alarm condition"
|
||||
tag = (ConditionTag) alarmContent.getTag();
|
||||
boolean showAlarm = tag != null && tag.condition != null;
|
||||
mZenRadioGroup.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(
|
||||
showAlarm ? View.VISIBLE : View.GONE);
|
||||
alarmContent.setVisibility(showAlarm ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
private void onClickTimeButton(View row, ConditionTag tag, boolean up, int rowId) {
|
||||
MetricsLogger.action(mContext, MetricsProto.MetricsEvent.QS_DND_TIME, up);
|
||||
Condition newCondition = null;
|
||||
final int N = MINUTE_BUCKETS.length;
|
||||
if (mBucketIndex == -1) {
|
||||
// not on a known index, search for the next or prev bucket by time
|
||||
final Uri conditionId = getConditionId(tag.condition);
|
||||
final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
|
||||
final long now = System.currentTimeMillis();
|
||||
for (int i = 0; i < N; i++) {
|
||||
int j = up ? i : N - 1 - i;
|
||||
final int bucketMinutes = MINUTE_BUCKETS[j];
|
||||
final long bucketTime = now + bucketMinutes * MINUTES_MS;
|
||||
if (up && bucketTime > time || !up && bucketTime < time) {
|
||||
mBucketIndex = j;
|
||||
newCondition = ZenModeConfig.toTimeCondition(mContext,
|
||||
bucketTime, bucketMinutes, ActivityManager.getCurrentUser(),
|
||||
false /*shortVersion*/);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newCondition == null) {
|
||||
mBucketIndex = DEFAULT_BUCKET_INDEX;
|
||||
newCondition = ZenModeConfig.toTimeCondition(mContext,
|
||||
MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
|
||||
}
|
||||
} else {
|
||||
// on a known index, simply increment or decrement
|
||||
mBucketIndex = Math.max(0, Math.min(N - 1, mBucketIndex + (up ? 1 : -1)));
|
||||
newCondition = ZenModeConfig.toTimeCondition(mContext,
|
||||
MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
|
||||
}
|
||||
bind(newCondition, row, rowId);
|
||||
tag.rb.setChecked(true);
|
||||
announceConditionSelection(tag);
|
||||
}
|
||||
|
||||
private void announceConditionSelection(ConditionTag tag) {
|
||||
// condition will always be priority-only
|
||||
String modeText = mContext.getString(R.string.zen_interruption_level_priority);
|
||||
if (tag.line1 != null) {
|
||||
mZenRadioGroupContent.announceForAccessibility(mContext.getString(
|
||||
R.string.zen_mode_and_condition, modeText, tag.line1.getText()));
|
||||
}
|
||||
}
|
||||
|
||||
// used as the view tag on condition rows
|
||||
@VisibleForTesting
|
||||
protected static class ConditionTag {
|
||||
public RadioButton rb;
|
||||
public View lines;
|
||||
public TextView line1;
|
||||
public TextView line2;
|
||||
public Condition condition;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.notification;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.preference.PreferenceViewHolder;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Switch;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.TwoTargetPreference;
|
||||
|
||||
/**
|
||||
* Shows an app icon, title and summary. Has a second switch touch target.
|
||||
*/
|
||||
public class NotificationAppPreference extends TwoTargetPreference {
|
||||
|
||||
private int mProgress;
|
||||
private boolean mProgressVisible;
|
||||
private Switch mSwitch;
|
||||
private boolean mChecked;
|
||||
private boolean mEnableSwitch = true;
|
||||
|
||||
public NotificationAppPreference(Context context) {
|
||||
super(context);
|
||||
setLayoutResource(R.layout.preference_app);
|
||||
}
|
||||
|
||||
public NotificationAppPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setLayoutResource(R.layout.preference_app);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSecondTargetResId() {
|
||||
return R.layout.preference_widget_master_switch;
|
||||
}
|
||||
|
||||
public void setProgress(int amount) {
|
||||
mProgress = amount;
|
||||
mProgressVisible = true;
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder view) {
|
||||
super.onBindViewHolder(view);
|
||||
|
||||
view.findViewById(R.id.summary_container)
|
||||
.setVisibility(TextUtils.isEmpty(getSummary()) ? View.GONE : View.VISIBLE);
|
||||
final ProgressBar progress = (ProgressBar) view.findViewById(android.R.id.progress);
|
||||
if (mProgressVisible) {
|
||||
progress.setProgress(mProgress);
|
||||
progress.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
progress.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
final View widgetView = view.findViewById(android.R.id.widget_frame);
|
||||
if (widgetView != null) {
|
||||
widgetView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mSwitch != null && !mSwitch.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
setChecked(!mChecked);
|
||||
if (!callChangeListener(mChecked)) {
|
||||
setChecked(!mChecked);
|
||||
} else {
|
||||
persistBoolean(mChecked);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
mSwitch = (Switch) view.findViewById(R.id.switchWidget);
|
||||
if (mSwitch != null) {
|
||||
mSwitch.setContentDescription(getTitle());
|
||||
mSwitch.setChecked(mChecked);
|
||||
mSwitch.setEnabled(mEnableSwitch);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isChecked() {
|
||||
return mSwitch != null && mChecked;
|
||||
}
|
||||
|
||||
public void setChecked(boolean checked) {
|
||||
mChecked = checked;
|
||||
if (mSwitch != null) {
|
||||
mSwitch.setChecked(checked);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSwitchEnabled(boolean enabled) {
|
||||
mEnableSwitch = enabled;
|
||||
if (mSwitch != null) {
|
||||
mSwitch.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If admin is not null, disables the switch.
|
||||
* Otherwise, keep it enabled.
|
||||
*/
|
||||
public void setDisabledByAdmin(RestrictedLockUtils.EnforcedAdmin admin) {
|
||||
setSwitchEnabled(admin == null);
|
||||
}
|
||||
|
||||
public Switch getSwitch() {
|
||||
return mSwitch;
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package com.android.settings.notification;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_NONE;
|
||||
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
|
||||
|
||||
import android.app.INotificationManager;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationChannelGroup;
|
||||
@@ -101,6 +104,12 @@ public class NotificationBackend {
|
||||
|
||||
public boolean setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled) {
|
||||
try {
|
||||
if (onlyHasDefaultChannel(pkg, uid)) {
|
||||
NotificationChannel defaultChannel =
|
||||
getChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
|
||||
defaultChannel.setImportance(enabled ? IMPORTANCE_UNSPECIFIED : IMPORTANCE_NONE);
|
||||
updateChannel(pkg, uid, defaultChannel);
|
||||
}
|
||||
sINM.setNotificationsEnabledForPackage(pkg, uid, enabled);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -74,6 +74,7 @@ import android.widget.Toast;
|
||||
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
@@ -252,30 +253,6 @@ abstract public class NotificationSettingsBase extends DashboardFragment {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void populateGroupToggle(final PreferenceGroup parent,
|
||||
NotificationChannelGroup group) {
|
||||
RestrictedSwitchPreference preference = new RestrictedSwitchPreference(getPrefContext());
|
||||
preference.setTitle(R.string.notification_switch_label);
|
||||
preference.setEnabled(mSuspendedAppsAdmin == null
|
||||
&& isChannelGroupBlockable(group));
|
||||
preference.setChecked(!group.isBlocked());
|
||||
preference.setOnPreferenceClickListener(preference1 -> {
|
||||
final boolean allowGroup = ((SwitchPreference) preference1).isChecked();
|
||||
group.setBlocked(!allowGroup);
|
||||
mBackend.updateChannelGroup(mAppRow.pkg, mAppRow.uid, group);
|
||||
|
||||
for (int i = 0; i < parent.getPreferenceCount(); i++) {
|
||||
Preference pref = parent.getPreference(i);
|
||||
if (pref instanceof MasterSwitchPreference) {
|
||||
((MasterSwitchPreference) pref).setSwitchEnabled(allowGroup);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
parent.addPreference(preference);
|
||||
}
|
||||
|
||||
protected Preference populateSingleChannelPrefs(PreferenceGroup parent,
|
||||
final NotificationChannel channel, final boolean groupBlocked) {
|
||||
MasterCheckBoxPreference channelPref = new MasterCheckBoxPreference(
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.service.notification.NotifyingApp;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
@@ -32,6 +33,7 @@ import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.IconDrawableFactory;
|
||||
import android.util.Log;
|
||||
import android.widget.Switch;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
@@ -40,6 +42,7 @@ import com.android.settings.applications.AppInfoBase;
|
||||
import com.android.settings.applications.InstalledAppCounter;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.widget.AppPreference;
|
||||
import com.android.settings.widget.MasterSwitchPreference;
|
||||
import com.android.settingslib.applications.AppUtils;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
@@ -197,13 +200,13 @@ public class RecentNotifyingAppsPreferenceController extends AbstractPreferenceC
|
||||
|
||||
// Rebind prefs/avoid adding new prefs if possible. Adding/removing prefs causes jank.
|
||||
// Build a cached preference pool
|
||||
final Map<String, Preference> appPreferences = new ArrayMap<>();
|
||||
final Map<String, NotificationAppPreference> appPreferences = new ArrayMap<>();
|
||||
int prefCount = mCategory.getPreferenceCount();
|
||||
for (int i = 0; i < prefCount; i++) {
|
||||
final Preference pref = mCategory.getPreference(i);
|
||||
final String key = pref.getKey();
|
||||
if (!TextUtils.equals(key, KEY_SEE_ALL)) {
|
||||
appPreferences.put(key, pref);
|
||||
appPreferences.put(key, (NotificationAppPreference) pref);
|
||||
}
|
||||
}
|
||||
final int recentAppsCount = recentApps.size();
|
||||
@@ -218,9 +221,9 @@ public class RecentNotifyingAppsPreferenceController extends AbstractPreferenceC
|
||||
}
|
||||
|
||||
boolean rebindPref = true;
|
||||
Preference pref = appPreferences.remove(pkgName);
|
||||
NotificationAppPreference pref = appPreferences.remove(pkgName);
|
||||
if (pref == null) {
|
||||
pref = new AppPreference(prefContext);
|
||||
pref = new NotificationAppPreference(prefContext);
|
||||
rebindPref = false;
|
||||
}
|
||||
pref.setKey(pkgName);
|
||||
@@ -229,13 +232,23 @@ public class RecentNotifyingAppsPreferenceController extends AbstractPreferenceC
|
||||
pref.setSummary(Utils.formatRelativeTime(mContext,
|
||||
System.currentTimeMillis() - app.getLastNotified(), false));
|
||||
pref.setOrder(i);
|
||||
pref.setOnPreferenceClickListener(preference -> {
|
||||
AppInfoBase.startAppInfoFragment(AppNotificationSettings.class,
|
||||
R.string.notifications_title, pkgName, appEntry.info.uid, mHost,
|
||||
1001 /*RequestCode */,
|
||||
MetricsProto.MetricsEvent.MANAGE_APPLICATIONS_NOTIFICATIONS);
|
||||
return true;
|
||||
Bundle args = new Bundle();
|
||||
args.putString(AppInfoBase.ARG_PACKAGE_NAME, pkgName);
|
||||
args.putInt(AppInfoBase.ARG_PACKAGE_UID, appEntry.info.uid);
|
||||
|
||||
pref.setIntent(Utils.onBuildStartFragmentIntent(mHost.getActivity(),
|
||||
AppNotificationSettings.class.getName(), args, null,
|
||||
R.string.notifications_title, null, false,
|
||||
MetricsProto.MetricsEvent.MANAGE_APPLICATIONS_NOTIFICATIONS));
|
||||
pref.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
boolean blocked = !(Boolean) newValue;
|
||||
mNotificationBackend.setNotificationsEnabledForPackage(
|
||||
pkgName, appEntry.info.uid, !blocked);
|
||||
return true;
|
||||
});
|
||||
pref.setChecked(
|
||||
!mNotificationBackend.getNotificationsBanned(pkgName, appEntry.info.uid));
|
||||
|
||||
if (!rebindPref) {
|
||||
mCategory.addPreference(pref);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.notification;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
|
||||
public class SettingsEnableZenModeDialog extends InstrumentedDialogFragment {
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return new com.android.settingslib.notification.EnableZenModeDialog(
|
||||
getContext()).createDialog();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.NOTIFICATION_ZEN_MODE_ENABLE_DIALOG;
|
||||
}
|
||||
}
|
||||
@@ -180,7 +180,7 @@ public class SoundSettings extends DashboardFragment {
|
||||
SoundSettings fragment, VolumeSeekBarPreference.Callback callback,
|
||||
Lifecycle lifecycle) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new ZenModePreferenceController(context));
|
||||
controllers.add(new ZenModePreferenceController(context, lifecycle));
|
||||
controllers.add(new VibrateWhenRingPreferenceController(context));
|
||||
|
||||
// === Volumes ===
|
||||
@@ -264,7 +264,7 @@ public class SoundSettings extends DashboardFragment {
|
||||
public List<String> getNonIndexableKeys(Context context) {
|
||||
List<String> keys = super.getNonIndexableKeys(context);
|
||||
// Duplicate results
|
||||
keys.add((new ZenModePreferenceController(context)).getPreferenceKey());
|
||||
keys.add((new ZenModePreferenceController(context, null)).getPreferenceKey());
|
||||
return keys;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
import android.support.v14.preference.PreferenceFragment;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.util.Slog;
|
||||
@@ -101,6 +102,13 @@ public class ZenAutomaticRuleHeaderPreferenceController extends AbstractZenModeP
|
||||
PackageManager packageManager = mContext.getPackageManager();
|
||||
ApplicationInfo info = packageManager.getApplicationInfo(
|
||||
mRule.getOwner().getPackageName(), 0);
|
||||
if (info.isSystemApp()) {
|
||||
if (ZenModeConfig.isValidScheduleConditionId(mRule.getConditionId())) {
|
||||
return mContext.getDrawable(R.drawable.ic_timelapse);
|
||||
} else if (ZenModeConfig.isValidEventConditionId(mRule.getConditionId())) {
|
||||
return mContext.getDrawable(R.drawable.ic_event);
|
||||
}
|
||||
}
|
||||
return info.loadIcon(packageManager);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Slog.w(TAG, "Unable to load icon - PackageManager.NameNotFoundException");
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.widget.Switch;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.LayoutPreference;
|
||||
@@ -36,14 +35,11 @@ public class ZenAutomaticRuleSwitchPreferenceController extends
|
||||
private static final String KEY = "zen_automatic_rule_switch";
|
||||
private AutomaticZenRule mRule;
|
||||
private String mId;
|
||||
private Toast mEnabledToast;
|
||||
private int mToastTextResource;
|
||||
private SwitchBar mSwitchBar;
|
||||
|
||||
public ZenAutomaticRuleSwitchPreferenceController(Context context, Fragment parent,
|
||||
int toastTextResource, Lifecycle lifecycle) {
|
||||
Lifecycle lifecycle) {
|
||||
super(context, KEY, parent, lifecycle);
|
||||
mToastTextResource = toastTextResource;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,16 +88,5 @@ public class ZenAutomaticRuleSwitchPreferenceController extends
|
||||
if (enabled == mRule.isEnabled()) return;
|
||||
mRule.setEnabled(enabled);
|
||||
mBackend.setZenRule(mId, mRule);
|
||||
if (enabled) {
|
||||
final int toastText = mToastTextResource;
|
||||
if (toastText != 0) {
|
||||
mEnabledToast = Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT);
|
||||
mEnabledToast.show();
|
||||
}
|
||||
} else {
|
||||
if (mEnabledToast != null) {
|
||||
mEnabledToast.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class ZenModeButtonPreferenceController extends AbstractZenModePreference
|
||||
mZenButtonOn = (Button) ((LayoutPreference) preference)
|
||||
.findViewById(R.id.zen_mode_settings_turn_on_button);
|
||||
mZenButtonOn.setOnClickListener(v ->
|
||||
new EnableZenModeDialog().show(mFragment, TAG));
|
||||
new SettingsEnableZenModeDialog().show(mFragment, TAG));
|
||||
}
|
||||
|
||||
if (null == mZenButtonOff) {
|
||||
|
||||
@@ -82,8 +82,7 @@ public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase {
|
||||
List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
mHeader = new ZenAutomaticRuleHeaderPreferenceController(context, this,
|
||||
getLifecycle());
|
||||
mSwitch = new ZenAutomaticRuleSwitchPreferenceController(context, this,
|
||||
R.string.zen_event_rule_enabled_toast, getLifecycle());
|
||||
mSwitch = new ZenAutomaticRuleSwitchPreferenceController(context, this, getLifecycle());
|
||||
controllers.add(mHeader);
|
||||
controllers.add(mSwitch);
|
||||
return controllers;
|
||||
|
||||
@@ -16,18 +16,56 @@
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.util.Slog;
|
||||
|
||||
public class ZenModePreferenceController extends AdjustVolumeRestrictedPreferenceController {
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
|
||||
public class ZenModePreferenceController extends AdjustVolumeRestrictedPreferenceController
|
||||
implements LifecycleObserver, OnResume, OnPause {
|
||||
|
||||
private static final String KEY_ZEN_MODE = "zen_mode";
|
||||
|
||||
private SettingObserver mSettingObserver;
|
||||
private ZenModeSettings.SummaryBuilder mSummaryBuilder;
|
||||
|
||||
public ZenModePreferenceController(Context context) {
|
||||
public ZenModePreferenceController(Context context, Lifecycle lifecycle) {
|
||||
super(context);
|
||||
mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
|
||||
|
||||
if (lifecycle != null) {
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mSettingObserver = new SettingObserver(screen.findPreference(KEY_ZEN_MODE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
if (mSettingObserver != null) {
|
||||
mSettingObserver.register(mContext.getContentResolver());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (mSettingObserver != null) {
|
||||
mSettingObserver.unregister(mContext.getContentResolver());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -44,7 +82,41 @@ public class ZenModePreferenceController extends AdjustVolumeRestrictedPreferenc
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
if (preference.isEnabled()) {
|
||||
preference.setSummary(mSummaryBuilder.getAutomaticRulesSummary());
|
||||
preference.setSummary(mSummaryBuilder.getSoundSummary());
|
||||
}
|
||||
}
|
||||
|
||||
class SettingObserver extends ContentObserver {
|
||||
private final Uri ZEN_MODE_URI = Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
|
||||
private final Uri ZEN_MODE_CONFIG_ETAG_URI = Settings.Global.getUriFor(
|
||||
Settings.Global.ZEN_MODE_CONFIG_ETAG);
|
||||
|
||||
private final Preference mPreference;
|
||||
|
||||
public SettingObserver(Preference preference) {
|
||||
super(new Handler());
|
||||
mPreference = preference;
|
||||
}
|
||||
|
||||
public void register(ContentResolver cr) {
|
||||
cr.registerContentObserver(ZEN_MODE_URI, false, this, UserHandle.USER_ALL);
|
||||
cr.registerContentObserver(ZEN_MODE_CONFIG_ETAG_URI, false, this, UserHandle.USER_ALL);
|
||||
}
|
||||
|
||||
public void unregister(ContentResolver cr) {
|
||||
cr.unregisterContentObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
super.onChange(selfChange, uri);
|
||||
if (ZEN_MODE_URI.equals(uri)) {
|
||||
updateState(mPreference);
|
||||
}
|
||||
|
||||
if (ZEN_MODE_CONFIG_ETAG_URI.equals(uri)) {
|
||||
updateState(mPreference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,8 +200,7 @@ public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
|
||||
List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
mHeader = new ZenAutomaticRuleHeaderPreferenceController(context, this,
|
||||
getLifecycle());
|
||||
mSwitch = new ZenAutomaticRuleSwitchPreferenceController(context, this,
|
||||
R.string.zen_schedule_rule_enabled_toast, getLifecycle());
|
||||
mSwitch = new ZenAutomaticRuleSwitchPreferenceController(context, this, getLifecycle());
|
||||
|
||||
controllers.add(mHeader);
|
||||
controllers.add(mSwitch);
|
||||
|
||||
@@ -115,6 +115,26 @@ public class ZenModeSettings extends ZenModeSettingsBase {
|
||||
return mContext.getString(R.string.zen_mode_behavior_summary_custom);
|
||||
}
|
||||
|
||||
String getSoundSummary() {
|
||||
int zenMode = NotificationManager.from(mContext).getZenMode();
|
||||
|
||||
if (zenMode != Settings.Global.ZEN_MODE_OFF) {
|
||||
Policy policy = NotificationManager.from(mContext).getNotificationPolicy();
|
||||
return mContext.getString(R.string.zen_mode_sound_summary_on,
|
||||
getBehaviorSettingSummary(policy, zenMode));
|
||||
} else {
|
||||
final int count = getEnabledAutomaticRulesCount();
|
||||
if (count > 0) {
|
||||
return mContext.getString(R.string.zen_mode_sound_summary_off_with_info,
|
||||
mContext.getResources().getQuantityString(
|
||||
R.plurals.zen_mode_sound_summary_summary_off_info,
|
||||
count, count));
|
||||
}
|
||||
|
||||
return mContext.getString(R.string.zen_mode_sound_summary_off);
|
||||
}
|
||||
}
|
||||
|
||||
String getAutomaticRulesSummary() {
|
||||
final int count = getEnabledAutomaticRulesCount();
|
||||
return count == 0 ? mContext.getString(R.string.zen_mode_settings_summary_off)
|
||||
|
||||
@@ -119,13 +119,21 @@ public class ZenRuleSelectionDialog extends InstrumentedDialogFragment {
|
||||
final LinearLayout v = (LinearLayout) LayoutInflater.from(mContext).inflate(
|
||||
R.layout.zen_rule_type, null, false);
|
||||
|
||||
LoadIconTask task = new LoadIconTask((ImageView) v.findViewById(R.id.icon));
|
||||
task.execute(info);
|
||||
ImageView iconView = v.findViewById(R.id.icon);
|
||||
((TextView) v.findViewById(R.id.title)).setText(ri.title);
|
||||
if (!ri.isSystem) {
|
||||
LoadIconTask task = new LoadIconTask(iconView);
|
||||
task.execute(info);
|
||||
|
||||
TextView subtitle = (TextView) v.findViewById(R.id.subtitle);
|
||||
subtitle.setText(info.loadLabel(mPm));
|
||||
subtitle.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
if (ZenModeConfig.isValidScheduleConditionId(ri.defaultConditionId)) {
|
||||
iconView.setImageDrawable(mContext.getDrawable(R.drawable.ic_timelapse));
|
||||
} else if (ZenModeConfig.isValidEventConditionId(ri.defaultConditionId)) {
|
||||
iconView.setImageDrawable(mContext.getDrawable(R.drawable.ic_event));
|
||||
}
|
||||
}
|
||||
v.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment;
|
||||
import com.android.settings.accessibility.AccessibilitySettings;
|
||||
import com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment;
|
||||
import com.android.settings.accessibility.MagnificationPreferenceFragment;
|
||||
import com.android.settings.accessibility.VibrationSettings;
|
||||
import com.android.settings.accounts.AccountDashboardFragment;
|
||||
import com.android.settings.applications.AppAndNotificationDashboardFragment;
|
||||
import com.android.settings.applications.DefaultAppSettings;
|
||||
@@ -49,7 +50,7 @@ import com.android.settings.display.NightDisplaySettings;
|
||||
import com.android.settings.display.ScreenZoomSettings;
|
||||
import com.android.settings.dream.DreamSettings;
|
||||
import com.android.settings.enterprise.EnterprisePrivacySettings;
|
||||
import com.android.settings.fuelgauge.BatterySaverSettings;
|
||||
import com.android.settings.fuelgauge.batterysaver.BatterySaverSettings;
|
||||
import com.android.settings.fuelgauge.PowerUsageAdvanced;
|
||||
import com.android.settings.fuelgauge.PowerUsageSummary;
|
||||
import com.android.settings.fuelgauge.SmartBatterySettings;
|
||||
@@ -176,6 +177,7 @@ public class SearchIndexableResourcesImpl implements SearchIndexableResources {
|
||||
addIndex(NightDisplaySettings.class);
|
||||
addIndex(SmartBatterySettings.class);
|
||||
addIndex(MyDeviceInfoFragment.class);
|
||||
addIndex(VibrationSettings.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.R;
|
||||
@@ -52,21 +51,18 @@ public class ManageTrustAgentsPreferenceController extends BasePreferenceControl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
final Preference preference = screen.findPreference(getPreferenceKey());
|
||||
if (preference == null) {
|
||||
return;
|
||||
}
|
||||
public void updateState(Preference preference) {
|
||||
final int numberOfTrustAgent = getTrustAgentCount();
|
||||
if (!mLockPatternUtils.isSecure(MY_USER_ID)) {
|
||||
preference.setEnabled(false);
|
||||
preference.setSummary(R.string.disabled_because_no_backup_security);
|
||||
} else if (numberOfTrustAgent > 0) {
|
||||
preference.setEnabled(true);
|
||||
preference.setSummary(mContext.getResources().getQuantityString(
|
||||
R.plurals.manage_trust_agents_summary_on,
|
||||
numberOfTrustAgent, numberOfTrustAgent));
|
||||
} else {
|
||||
preference.setEnabled(true);
|
||||
preference.setSummary(R.string.manage_trust_agents_summary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,8 @@ public class WallpaperSuggestionActivity extends Activity {
|
||||
@VisibleForTesting
|
||||
public static boolean isSuggestionComplete(Context context) {
|
||||
final WallpaperManagerWrapper manager = new WallpaperManagerWrapper(context);
|
||||
return manager.getWallpaperId(WallpaperManager.FLAG_SYSTEM) > 0;
|
||||
return manager.isWallpaperServiceEnabled() ? manager.getWallpaperId(
|
||||
WallpaperManager.FLAG_SYSTEM) > 0 : false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ public class SeekBarPreference extends RestrictedPreference
|
||||
|
||||
private int mProgress;
|
||||
private int mMax;
|
||||
private int mMin;
|
||||
private boolean mTrackingTouch;
|
||||
|
||||
private boolean mContinuousUpdates;
|
||||
@@ -55,6 +56,7 @@ public class SeekBarPreference extends RestrictedPreference
|
||||
TypedArray a = context.obtainStyledAttributes(
|
||||
attrs, com.android.internal.R.styleable.ProgressBar, defStyleAttr, defStyleRes);
|
||||
setMax(a.getInt(com.android.internal.R.styleable.ProgressBar_max, mMax));
|
||||
setMin(a.getInt(com.android.internal.R.styleable.ProgressBar_min, mMin));
|
||||
a.recycle();
|
||||
|
||||
a = context.obtainStyledAttributes(attrs,
|
||||
@@ -94,6 +96,7 @@ public class SeekBarPreference extends RestrictedPreference
|
||||
com.android.internal.R.id.seekbar);
|
||||
mSeekBar.setOnSeekBarChangeListener(this);
|
||||
mSeekBar.setMax(mMax);
|
||||
mSeekBar.setMin(mMin);
|
||||
mSeekBar.setProgress(mProgress);
|
||||
mSeekBar.setEnabled(isEnabled());
|
||||
final CharSequence title = getTitle();
|
||||
@@ -154,10 +157,21 @@ public class SeekBarPreference extends RestrictedPreference
|
||||
}
|
||||
}
|
||||
|
||||
public void setMin(int min) {
|
||||
if (min != mMin) {
|
||||
mMin = min;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public int getMax() {
|
||||
return mMax;
|
||||
}
|
||||
|
||||
public int getMin() {
|
||||
return mMin;
|
||||
}
|
||||
|
||||
public void setProgress(int progress) {
|
||||
setProgress(progress, true);
|
||||
}
|
||||
@@ -187,8 +201,8 @@ public class SeekBarPreference extends RestrictedPreference
|
||||
if (progress > mMax) {
|
||||
progress = mMax;
|
||||
}
|
||||
if (progress < 0) {
|
||||
progress = 0;
|
||||
if (progress < mMin) {
|
||||
progress = mMin;
|
||||
}
|
||||
if (progress != mProgress) {
|
||||
mProgress = progress;
|
||||
@@ -257,6 +271,7 @@ public class SeekBarPreference extends RestrictedPreference
|
||||
final SavedState myState = new SavedState(superState);
|
||||
myState.progress = mProgress;
|
||||
myState.max = mMax;
|
||||
myState.min = mMin;
|
||||
return myState;
|
||||
}
|
||||
|
||||
@@ -273,6 +288,7 @@ public class SeekBarPreference extends RestrictedPreference
|
||||
super.onRestoreInstanceState(myState.getSuperState());
|
||||
mProgress = myState.progress;
|
||||
mMax = myState.max;
|
||||
mMin = myState.min;
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
@@ -285,6 +301,7 @@ public class SeekBarPreference extends RestrictedPreference
|
||||
private static class SavedState extends BaseSavedState {
|
||||
int progress;
|
||||
int max;
|
||||
int min;
|
||||
|
||||
public SavedState(Parcel source) {
|
||||
super(source);
|
||||
@@ -292,6 +309,7 @@ public class SeekBarPreference extends RestrictedPreference
|
||||
// Restore the click counter
|
||||
progress = source.readInt();
|
||||
max = source.readInt();
|
||||
min = source.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -301,6 +319,7 @@ public class SeekBarPreference extends RestrictedPreference
|
||||
// Save the click counter
|
||||
dest.writeInt(progress);
|
||||
dest.writeInt(max);
|
||||
dest.writeInt(min);
|
||||
}
|
||||
|
||||
public SavedState(Parcelable superState) {
|
||||
|
||||
@@ -36,6 +36,7 @@ public class ConnectedAccessPointPreference extends AccessPointPreference implem
|
||||
public ConnectedAccessPointPreference(AccessPoint accessPoint, Context context,
|
||||
UserBadgeCache cache, @DrawableRes int iconResId, boolean forSavedNetworks) {
|
||||
super(accessPoint, context, cache, iconResId, forSavedNetworks);
|
||||
setWidgetLayoutResource(R.layout.preference_widget_gear_no_bg);
|
||||
}
|
||||
|
||||
public void setOnGearClickListener(OnGearClickListener l) {
|
||||
@@ -43,26 +44,6 @@ public class ConnectedAccessPointPreference extends AccessPointPreference implem
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSecondTargetResId() {
|
||||
return R.layout.preference_widget_gear;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldHideSecondTarget() {
|
||||
return mOnGearClickListener == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
final View gear = holder.findViewById(R.id.settings_button);
|
||||
if (gear != null) {
|
||||
gear.setOnClickListener(this);
|
||||
}
|
||||
setDividerVisibility(holder, View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.getId() == R.id.settings_button) {
|
||||
|
||||
@@ -884,13 +884,14 @@ public class WifiSettings extends RestrictedSettingsFragment
|
||||
connectedAp);
|
||||
|
||||
// Launch details page on click.
|
||||
pref.setOnGearClickListener(l -> {
|
||||
pref.setOnPreferenceClickListener(preference -> {
|
||||
pref.getAccessPoint().saveWifiState(pref.getExtras());
|
||||
|
||||
SettingsActivity activity = (SettingsActivity) WifiSettings.this.getActivity();
|
||||
activity.startPreferencePanel(this,
|
||||
WifiNetworkDetailsFragment.class.getName(), pref.getExtras(),
|
||||
-1 /* resId */, pref.getTitle(), null, 0 /* resultRequestCode */);
|
||||
return true;
|
||||
});
|
||||
|
||||
pref.refresh();
|
||||
|
||||
@@ -22,12 +22,23 @@ import android.content.Context;
|
||||
public class WallpaperManagerWrapper {
|
||||
|
||||
private final WallpaperManager mWallpaperManager;
|
||||
private final boolean mWallpaperServiceEnabled;
|
||||
|
||||
public WallpaperManagerWrapper(Context context) {
|
||||
mWallpaperManager = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
|
||||
mWallpaperServiceEnabled = context.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_enableWallpaperService);
|
||||
mWallpaperManager = mWallpaperServiceEnabled ? (WallpaperManager) context.getSystemService(
|
||||
Context.WALLPAPER_SERVICE) : null;
|
||||
}
|
||||
|
||||
public boolean isWallpaperServiceEnabled() {
|
||||
return mWallpaperServiceEnabled;
|
||||
}
|
||||
|
||||
public int getWallpaperId(int which) {
|
||||
if (!mWallpaperServiceEnabled) {
|
||||
throw new RuntimeException("This device does not have wallpaper service enabled.");
|
||||
}
|
||||
return mWallpaperManager.getWallpaperId(which);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
package com.android.internal.app;
|
||||
|
||||
/**
|
||||
* Fake controller to make robolectric test compile. Should be removed when Robolectric supports
|
||||
* API 25.
|
||||
* Fake controller to make robolectric test compile. This is necessary since
|
||||
* ColorDisplayController is not part of Android's API.
|
||||
*/
|
||||
public class ColorDisplayController {
|
||||
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.accessibility;
|
||||
|
||||
import static com.android.settings.accessibility.VibrationPreferenceFragment.KEY_INTENSITY_OFF;
|
||||
import static com.android.settings.accessibility.VibrationPreferenceFragment.KEY_INTENSITY_LOW;
|
||||
import static com.android.settings.accessibility.VibrationPreferenceFragment.KEY_INTENSITY_MEDIUM;
|
||||
import static com.android.settings.accessibility.VibrationPreferenceFragment.KEY_INTENSITY_HIGH;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.UserManager;
|
||||
import android.os.Vibrator;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.accessibility.VibrationPreferenceFragment.VibrationIntensityCandidateInfo;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.widget.RadioButtonPickerFragment.CandidateInfo;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class VibrationPreferenceFragmentTest {
|
||||
public static final Map<Integer, String> INTENSITY_TO_KEY = new HashMap<>();
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private Activity mActivity;
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
|
||||
private Context mContext;
|
||||
private TestVibrationPreferenceFragment mFragment;
|
||||
|
||||
static {
|
||||
INTENSITY_TO_KEY.put(Vibrator.VIBRATION_INTENSITY_OFF, KEY_INTENSITY_OFF);
|
||||
INTENSITY_TO_KEY.put(Vibrator.VIBRATION_INTENSITY_LOW, KEY_INTENSITY_LOW);
|
||||
INTENSITY_TO_KEY.put(Vibrator.VIBRATION_INTENSITY_MEDIUM, KEY_INTENSITY_MEDIUM);
|
||||
INTENSITY_TO_KEY.put(Vibrator.VIBRATION_INTENSITY_HIGH, KEY_INTENSITY_HIGH);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
FakeFeatureFactory.setupForTest();
|
||||
|
||||
mContext = RuntimeEnvironment.application;
|
||||
|
||||
mFragment = spy(new TestVibrationPreferenceFragment());
|
||||
doReturn(mUserManager).when(mActivity).getSystemService(Context.USER_SERVICE);
|
||||
doReturn(mContext).when(mFragment).getContext();
|
||||
mFragment.onAttach(mActivity);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void changeIntensitySetting_shouldResultInCorrespondingKey() {
|
||||
for (Map.Entry<Integer, String> entry : INTENSITY_TO_KEY.entrySet()) {
|
||||
Settings.System.putInt(mContext.getContentResolver(),
|
||||
Settings.System.HAPTIC_FEEDBACK_INTENSITY, entry.getKey());
|
||||
assertThat(mFragment.getDefaultKey()).isEqualTo(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initialDefaultKey_shouldBeMedium() {
|
||||
assertThat(mFragment.getDefaultKey()).isEqualTo(KEY_INTENSITY_MEDIUM);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void candidates_shouldBeSortedByIntensity() {
|
||||
final List<? extends CandidateInfo> candidates = mFragment.getCandidates();
|
||||
assertThat(candidates.size()).isEqualTo(INTENSITY_TO_KEY.size());
|
||||
VibrationIntensityCandidateInfo prevCandidate =
|
||||
(VibrationIntensityCandidateInfo) candidates.get(0);
|
||||
for (int i = 1; i < candidates.size(); i++) {
|
||||
VibrationIntensityCandidateInfo candidate =
|
||||
(VibrationIntensityCandidateInfo) candidates.get(i);
|
||||
assertThat(candidate.getIntensity()).isLessThan(prevCandidate.getIntensity());
|
||||
}
|
||||
}
|
||||
|
||||
private class TestVibrationPreferenceFragment extends VibrationPreferenceFragment {
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the setting string of the vibration intensity setting this preference is dealing with.
|
||||
*/
|
||||
@Override
|
||||
protected String getVibrationIntensitySetting() {
|
||||
return Settings.System.HAPTIC_FEEDBACK_INTENSITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDefaultVibrationIntensity() {
|
||||
return Vibrator.VIBRATION_INTENSITY_MEDIUM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.support.v7.widget.RecyclerView;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.settings.R;
|
||||
@@ -77,6 +78,8 @@ public class DashboardAdapterTest {
|
||||
private Condition mCondition;
|
||||
@Mock
|
||||
private Resources mResources;
|
||||
@Mock
|
||||
private WindowManager mWindowManager;
|
||||
private FakeFeatureFactory mFactory;
|
||||
private DashboardAdapter mDashboardAdapter;
|
||||
private List<Condition> mConditionList;
|
||||
@@ -87,6 +90,7 @@ public class DashboardAdapterTest {
|
||||
mFactory = FakeFeatureFactory.setupForTest();
|
||||
when(mFactory.dashboardFeatureProvider.shouldTintIcon()).thenReturn(true);
|
||||
|
||||
when(mContext.getSystemService(Context.WINDOW_SERVICE)).thenReturn(mWindowManager);
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
when(mResources.getQuantityString(any(int.class), any(int.class), any()))
|
||||
.thenReturn("");
|
||||
|
||||
@@ -28,12 +28,15 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.service.settings.suggestions.Suggestion;
|
||||
import android.view.Display;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
@@ -67,17 +70,33 @@ public class SuggestionAdapterTest {
|
||||
private SettingsActivity mActivity;
|
||||
@Mock
|
||||
private SuggestionControllerMixin mSuggestionControllerMixin;
|
||||
@Mock
|
||||
private Resources mResources;
|
||||
@Mock
|
||||
private WindowManager mWindowManager;
|
||||
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
private Context mContext;
|
||||
private SuggestionAdapter mSuggestionAdapter;
|
||||
private DashboardAdapter.DashboardItemHolder mSuggestionHolder;
|
||||
private List<Suggestion> mOneSuggestion;
|
||||
private List<Suggestion> mTwoSuggestions;
|
||||
private SuggestionAdapter.CardConfig mConfig;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
when(mActivity.getSystemService(Context.WINDOW_SERVICE)).thenReturn(mWindowManager);
|
||||
when(mActivity.getResources()).thenReturn(mResources);
|
||||
when(mResources.getDimensionPixelOffset(R.dimen.suggestion_card_inner_margin))
|
||||
.thenReturn(10);
|
||||
when(mResources.getDimensionPixelOffset(R.dimen.suggestion_card_outer_margin))
|
||||
.thenReturn(20);
|
||||
when(mResources.getDimensionPixelOffset(R.dimen.suggestion_card_width_multiple_cards))
|
||||
.thenReturn(120);
|
||||
mConfig = spy(SuggestionAdapter.CardConfig.get(mActivity));
|
||||
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
|
||||
final Suggestion suggestion1 = new Suggestion.Builder("id1")
|
||||
@@ -275,6 +294,44 @@ public class SuggestionAdapterTest {
|
||||
verify(drawable).setTint(colorAccent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setCardLayout_oneCard_shouldSetCardWidthToMatchParent() {
|
||||
final List<Suggestion> suggestions = makeSuggestions("pkg1");
|
||||
setupSuggestions(mContext, suggestions);
|
||||
|
||||
mConfig.setCardLayout(mSuggestionHolder, 1, 0);
|
||||
|
||||
assertThat(mSuggestionHolder.itemView.getLayoutParams().width)
|
||||
.isEqualTo(LinearLayout.LayoutParams.MATCH_PARENT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setCardLayout_twoCards_shouldSetCardWidthToHalfScreenMinusPadding() {
|
||||
final List<Suggestion> suggestions = makeSuggestions("pkg1");
|
||||
setupSuggestions(mContext, suggestions);
|
||||
doReturn(200).when(mConfig).getScreenWidth();
|
||||
|
||||
mConfig.setCardLayout(mSuggestionHolder, 2, 0);
|
||||
|
||||
/*
|
||||
* card width = (screen width - left margin - inner margin - right margin) / 2
|
||||
* = (200 - 20 - 10 - 20) / 2
|
||||
* = 75
|
||||
*/
|
||||
assertThat(mSuggestionHolder.itemView.getLayoutParams().width).isEqualTo(75);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void setCardLayout_multipleCards_shouldSetCardWidthFromResource() {
|
||||
final List<Suggestion> suggestions = makeSuggestions("pkg1");
|
||||
setupSuggestions(mContext, suggestions);
|
||||
|
||||
mConfig.setCardLayout(mSuggestionHolder, 3, 0);
|
||||
|
||||
assertThat(mSuggestionHolder.itemView.getLayoutParams().width).isEqualTo(120);
|
||||
}
|
||||
|
||||
private void setupSuggestions(Context context, List<Suggestion> suggestions) {
|
||||
mSuggestionAdapter = new SuggestionAdapter(context, mSuggestionControllerMixin,
|
||||
null /* savedInstanceState */, null /* callback */, null /* lifecycle */);
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.settings.fuelgauge;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.SearchIndexableResource;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class BatterySaverSettingsTest {
|
||||
private Context mContext;
|
||||
private BatterySaverSettings mBatterySaverSettings;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mBatterySaverSettings = new BatterySaverSettings();
|
||||
mBatterySaverSettings.mSwitchBar = new SwitchBar(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnBatteryChanged_pluggedIn_setDisable() {
|
||||
mBatterySaverSettings.onBatteryChanged(true /* pluggedIn */);
|
||||
|
||||
assertThat(mBatterySaverSettings.mSwitchBar.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnBatteryChanged_notPluggedIn_setEnable() {
|
||||
mBatterySaverSettings.onBatteryChanged(false /* pluggedIn */);
|
||||
|
||||
assertThat(mBatterySaverSettings.mSwitchBar.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchProvider_shouldIndexDefaultXml() {
|
||||
final List<SearchIndexableResource> sir = mBatterySaverSettings.SEARCH_INDEX_DATA_PROVIDER
|
||||
.getXmlResourcesToIndex(mContext, true /* enabled */);
|
||||
|
||||
assertThat(sir).hasSize(1);
|
||||
assertThat(sir.get(0).xmlResId).isEqualTo(R.xml.battery_saver_settings);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.settings.fuelgauge.batterysaver;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.support.v14.preference.SwitchPreference;
|
||||
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class AutoBatterySaverPreferenceControllerTest {
|
||||
|
||||
private AutoBatterySaverPreferenceController mController;
|
||||
private Context mContext;
|
||||
private SwitchPreference mPreference;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mPreference = new SwitchPreference(mContext);
|
||||
mController = new AutoBatterySaverPreferenceController(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_lowPowerLevelZero_preferenceNotChecked() {
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateState_lowPowerLevelZero_preferenceChecked() {
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 15);
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isChecked()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnPreferenceChange_turnOn_setValueNotZero() {
|
||||
mController.onPreferenceChange(mPreference, true);
|
||||
|
||||
assertThat(Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0)).isNotEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnPreferenceChange_turnOff_setValueZero() {
|
||||
mController.onPreferenceChange(mPreference, false);
|
||||
|
||||
assertThat(Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0)).isEqualTo(0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.fuelgauge.batterysaver;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.arch.lifecycle.LifecycleOwner;
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.support.v14.preference.SwitchPreference;
|
||||
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.widget.SeekBarPreference;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class AutoBatterySeekBarPreferenceControllerTest {
|
||||
private static final int TRIGGER_LEVEL = 15;
|
||||
|
||||
private AutoBatterySeekBarPreferenceController mController;
|
||||
private Context mContext;
|
||||
private SeekBarPreference mPreference;
|
||||
private Lifecycle mLifecycle;
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mLifecycleOwner = () -> mLifecycle;
|
||||
mLifecycle = new Lifecycle(mLifecycleOwner);
|
||||
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mPreference = new SeekBarPreference(mContext);
|
||||
mPreference.setMax(100);
|
||||
mController = new AutoBatterySeekBarPreferenceController(mContext, mLifecycle);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreference_lowPowerLevelZero_preferenceInvisible() {
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isVisible()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreference_lowPowerLevelNotZero_updatePreference() {
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, TRIGGER_LEVEL);
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isVisible()).isTrue();
|
||||
assertThat(mPreference.getTitle()).isEqualTo("Turn on automatically at 15%");
|
||||
assertThat(mPreference.getProgress()).isEqualTo(TRIGGER_LEVEL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnPreferenceChange_updateValue() {
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
|
||||
|
||||
mController.onPreferenceChange(mPreference, TRIGGER_LEVEL);
|
||||
|
||||
assertThat(Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0)).isEqualTo(TRIGGER_LEVEL);
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,9 @@ import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
@@ -238,19 +240,26 @@ public class BlockPreferenceControllerTest {
|
||||
@Test
|
||||
public void testOnSwitchChanged_channel_default() throws Exception {
|
||||
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
|
||||
appRow.pkg = "pkg";
|
||||
NotificationChannel channel =
|
||||
new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_UNSPECIFIED);
|
||||
when(mBackend.onlyHasDefaultChannel(anyString(), anyInt())).thenReturn(true);
|
||||
mController.onResume(appRow, channel, null, null);
|
||||
mController.updateState(mPreference);
|
||||
|
||||
mController.onSwitchChanged(null, false);
|
||||
assertEquals(IMPORTANCE_NONE, channel.getImportance());
|
||||
assertTrue(appRow.banned);
|
||||
|
||||
mController.onSwitchChanged(null, true);
|
||||
assertEquals(IMPORTANCE_UNSPECIFIED, channel.getImportance());
|
||||
assertFalse(appRow.banned);
|
||||
|
||||
verify(mBackend, times(2)).updateChannel(any(), anyInt(), any());
|
||||
|
||||
// 2 calls for onSwitchChanged + once when calling updateState originally
|
||||
verify(mBackend, times(3)).setNotificationsEnabledForPackage(
|
||||
anyString(), anyInt(), anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.notification;
|
||||
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.service.notification.Condition;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class EnableZenModeDialogTest {
|
||||
private EnableZenModeDialog mController;
|
||||
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private Activity mActivity;
|
||||
@Mock
|
||||
private Fragment mFragment;
|
||||
|
||||
private Context mShadowContext;
|
||||
private LayoutInflater mLayoutInflater;
|
||||
private Condition mCountdownCondition;
|
||||
private Condition mAlarmCondition;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mShadowContext = RuntimeEnvironment.application;
|
||||
when(mActivity.getApplicationContext()).thenReturn(mShadowContext);
|
||||
when(mContext.getApplicationContext()).thenReturn(mContext);
|
||||
when(mFragment.getContext()).thenReturn(mShadowContext);
|
||||
mLayoutInflater = LayoutInflater.from(mShadowContext);
|
||||
when(mActivity.getLayoutInflater()).thenReturn(mLayoutInflater);
|
||||
|
||||
mController = spy(new EnableZenModeDialog());
|
||||
mController.mContext = mContext;
|
||||
mController.mActivity = mActivity;
|
||||
mController.mForeverId = Condition.newId(mContext).appendPath("forever").build();
|
||||
when(mContext.getString(com.android.internal.R.string.zen_mode_forever))
|
||||
.thenReturn("testSummary");
|
||||
mController.getContentView();
|
||||
|
||||
// these methods use static calls to ZenModeConfig which would normally fail in robotests,
|
||||
// so instead do nothing:
|
||||
doNothing().when(mController).bindGenericCountdown();
|
||||
doReturn(null).when(mController).getTimeUntilNextAlarmCondition();
|
||||
doNothing().when(mController).bindNextAlarm(any());
|
||||
|
||||
// as a result of doing nothing above, must bind manually:
|
||||
Uri alarm = Condition.newId(mContext).appendPath("alarm").build();
|
||||
mAlarmCondition = new Condition(alarm, "alarm", "", "", 0, 0, 0);
|
||||
Uri countdown = Condition.newId(mContext).appendPath("countdown").build();
|
||||
mCountdownCondition = new Condition(countdown, "countdown", "", "", 0, 0, 0);
|
||||
mController.bind(mCountdownCondition,
|
||||
mController.mZenRadioGroupContent.getChildAt(
|
||||
EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX),
|
||||
EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX);
|
||||
mController.bind(mAlarmCondition,
|
||||
mController.mZenRadioGroupContent.getChildAt(
|
||||
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX),
|
||||
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForeverChecked() {
|
||||
mController.bindConditions(mController.forever());
|
||||
|
||||
assertTrue(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
|
||||
.isChecked());
|
||||
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
|
||||
.isChecked());
|
||||
assertFalse(mController.getConditionTagAt(
|
||||
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoneChecked() {
|
||||
mController.bindConditions(null);
|
||||
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
|
||||
.isChecked());
|
||||
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
|
||||
.isChecked());
|
||||
assertFalse(mController.getConditionTagAt(
|
||||
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlarmChecked() {
|
||||
doReturn(false).when(mController).isCountdown(mAlarmCondition);
|
||||
doReturn(true).when(mController).isAlarm(mAlarmCondition);
|
||||
|
||||
mController.bindConditions(mAlarmCondition);
|
||||
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
|
||||
.isChecked());
|
||||
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
|
||||
.isChecked());
|
||||
assertTrue(mController.getConditionTagAt(
|
||||
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountdownChecked() {
|
||||
doReturn(false).when(mController).isAlarm(mCountdownCondition);
|
||||
doReturn(true).when(mController).isCountdown(mCountdownCondition);
|
||||
|
||||
mController.bindConditions(mCountdownCondition);
|
||||
assertFalse(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
|
||||
.isChecked());
|
||||
assertTrue(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
|
||||
.isChecked());
|
||||
assertFalse(mController.getConditionTagAt(
|
||||
EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.notification;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceViewHolder;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Switch;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class NotificationAppPreferenceTest {
|
||||
|
||||
private Context mContext;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createNewPreference_shouldSetLayout() {
|
||||
final NotificationAppPreference preference = new NotificationAppPreference(mContext);
|
||||
assertThat(preference.getWidgetLayoutResource()).isEqualTo(
|
||||
R.layout.preference_widget_master_switch);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setChecked_shouldUpdateButtonCheckedState() {
|
||||
final NotificationAppPreference preference = new NotificationAppPreference(mContext);
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
|
||||
inflater.inflate(R.layout.preference_app, null));
|
||||
final LinearLayout widgetView = holder.itemView.findViewById(android.R.id.widget_frame);
|
||||
inflater.inflate(R.layout.preference_widget_master_switch, widgetView, true);
|
||||
final Switch toggle = (Switch) holder.findViewById(R.id.switchWidget);
|
||||
preference.onBindViewHolder(holder);
|
||||
|
||||
preference.setChecked(true);
|
||||
assertThat(toggle.isChecked()).isTrue();
|
||||
|
||||
preference.setChecked(false);
|
||||
assertThat(toggle.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSwitchEnabled_shouldUpdateButtonEnabledState() {
|
||||
final NotificationAppPreference preference = new NotificationAppPreference(mContext);
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
|
||||
inflater.inflate(R.layout.preference_app, null));
|
||||
final LinearLayout widgetView = holder.itemView.findViewById(android.R.id.widget_frame);
|
||||
inflater.inflate(R.layout.preference_widget_master_switch, widgetView, true);
|
||||
final Switch toggle = (Switch) holder.findViewById(R.id.switchWidget);
|
||||
preference.onBindViewHolder(holder);
|
||||
|
||||
preference.setSwitchEnabled(true);
|
||||
assertThat(toggle.isEnabled()).isTrue();
|
||||
|
||||
preference.setSwitchEnabled(false);
|
||||
assertThat(toggle.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSwitchEnabled_shouldUpdateButtonEnabledState_beforeViewBound() {
|
||||
final NotificationAppPreference preference = new NotificationAppPreference(mContext);
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
|
||||
inflater.inflate(R.layout.preference_app, null));
|
||||
final LinearLayout widgetView = holder.itemView.findViewById(android.R.id.widget_frame);
|
||||
inflater.inflate(R.layout.preference_widget_master_switch, widgetView, true);
|
||||
final Switch toggle = (Switch) holder.findViewById(R.id.switchWidget);
|
||||
|
||||
preference.setSwitchEnabled(false);
|
||||
preference.onBindViewHolder(holder);
|
||||
assertThat(toggle.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clickWidgetView_shouldToggleButton() {
|
||||
final NotificationAppPreference preference = new NotificationAppPreference(mContext);
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
|
||||
inflater.inflate(R.layout.preference_app, null));
|
||||
final LinearLayout widgetView = holder.itemView.findViewById(android.R.id.widget_frame);
|
||||
inflater.inflate(R.layout.preference_widget_master_switch, widgetView, true);
|
||||
final Switch toggle = (Switch) holder.findViewById(R.id.switchWidget);
|
||||
preference.onBindViewHolder(holder);
|
||||
|
||||
widgetView.performClick();
|
||||
assertThat(toggle.isChecked()).isTrue();
|
||||
|
||||
widgetView.performClick();
|
||||
assertThat(toggle.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clickWidgetView_shouldNotToggleButtonIfDisabled() {
|
||||
final NotificationAppPreference preference = new NotificationAppPreference(mContext);
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
|
||||
inflater.inflate(R.layout.preference_app, null));
|
||||
final LinearLayout widgetView = holder.itemView.findViewById(android.R.id.widget_frame);
|
||||
inflater.inflate(R.layout.preference_widget_master_switch, widgetView, true);
|
||||
final Switch toggle = (Switch) holder.findViewById(R.id.switchWidget);
|
||||
preference.onBindViewHolder(holder);
|
||||
toggle.setEnabled(false);
|
||||
|
||||
widgetView.performClick();
|
||||
assertThat(toggle.isChecked()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clickWidgetView_shouldNotifyPreferenceChanged() {
|
||||
final NotificationAppPreference preference = new NotificationAppPreference(mContext);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
|
||||
LayoutInflater.from(mContext).inflate(R.layout.preference_app, null));
|
||||
final View widgetView = holder.findViewById(android.R.id.widget_frame);
|
||||
final Preference.OnPreferenceChangeListener
|
||||
listener = mock(Preference.OnPreferenceChangeListener.class);
|
||||
preference.setOnPreferenceChangeListener(listener);
|
||||
preference.onBindViewHolder(holder);
|
||||
|
||||
preference.setChecked(false);
|
||||
widgetView.performClick();
|
||||
verify(listener).onPreferenceChange(preference, true);
|
||||
|
||||
preference.setChecked(true);
|
||||
widgetView.performClick();
|
||||
verify(listener).onPreferenceChange(preference, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setDisabledByAdmin_hasEnforcedAdmin_shouldDisableButton() {
|
||||
final NotificationAppPreference preference = new NotificationAppPreference(mContext);
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
|
||||
inflater.inflate(R.layout.preference_app, null));
|
||||
final LinearLayout widgetView = holder.itemView.findViewById(android.R.id.widget_frame);
|
||||
inflater.inflate(R.layout.preference_widget_master_switch, widgetView, true);
|
||||
final Switch toggle = (Switch) holder.findViewById(R.id.switchWidget);
|
||||
toggle.setEnabled(true);
|
||||
preference.onBindViewHolder(holder);
|
||||
|
||||
preference.setDisabledByAdmin(mock(RestrictedLockUtils.EnforcedAdmin.class));
|
||||
assertThat(toggle.isEnabled()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setDisabledByAdmin_noEnforcedAdmin_shouldEnableButton() {
|
||||
final NotificationAppPreference preference = new NotificationAppPreference(mContext);
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
|
||||
inflater.inflate(R.layout.preference_app, null));
|
||||
final LinearLayout widgetView = holder.itemView.findViewById(android.R.id.widget_frame);
|
||||
inflater.inflate(R.layout.preference_widget_master_switch, widgetView, true);
|
||||
final Switch toggle = (Switch) holder.findViewById(R.id.switchWidget);
|
||||
toggle.setEnabled(false);
|
||||
preference.onBindViewHolder(holder);
|
||||
|
||||
preference.setDisabledByAdmin(null);
|
||||
assertThat(toggle.isEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindViewHolder_toggleButtonShouldHaveContentDescription() {
|
||||
final NotificationAppPreference preference = new NotificationAppPreference(mContext);
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
|
||||
inflater.inflate(R.layout.preference_app, null));
|
||||
final LinearLayout widgetView = holder.itemView.findViewById(android.R.id.widget_frame);
|
||||
inflater.inflate(R.layout.preference_widget_master_switch, widgetView, true);
|
||||
final Switch toggle = (Switch) holder.findViewById(R.id.switchWidget);
|
||||
final String label = "TestButton";
|
||||
preference.setTitle(label);
|
||||
|
||||
preference.onBindViewHolder(holder);
|
||||
|
||||
assertThat(toggle.getContentDescription()).isEqualTo(label);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSummary_showSummaryContainer() {
|
||||
final NotificationAppPreference preference = new NotificationAppPreference(mContext);
|
||||
View rootView = View.inflate(mContext, R.layout.preference_app, null /* parent */);
|
||||
PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(rootView);
|
||||
preference.setSummary("test");
|
||||
preference.onBindViewHolder(holder);
|
||||
|
||||
assertThat(holder.findViewById(R.id.summary_container).getVisibility())
|
||||
.isEqualTo(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noSummary_hideSummaryContainer() {
|
||||
final NotificationAppPreference preference = new NotificationAppPreference(mContext);
|
||||
View rootView = View.inflate(mContext, R.layout.preference_app, null /* parent */);
|
||||
PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(rootView);
|
||||
preference.setSummary(null);
|
||||
preference.onBindViewHolder(holder);
|
||||
|
||||
assertThat(holder.findViewById(R.id.summary_container).getVisibility())
|
||||
.isEqualTo(View.GONE);
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,9 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.app.Fragment;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
@@ -90,6 +92,10 @@ public class RecentNotifyingAppsPreferenceControllerTest {
|
||||
private ApplicationInfo mApplicationInfo;
|
||||
@Mock
|
||||
private NotificationBackend mBackend;
|
||||
@Mock
|
||||
private Fragment mHost;
|
||||
@Mock
|
||||
private Activity mActivity;
|
||||
|
||||
private Context mContext;
|
||||
private RecentNotifyingAppsPreferenceController mController;
|
||||
@@ -102,7 +108,7 @@ public class RecentNotifyingAppsPreferenceControllerTest {
|
||||
doReturn(mPackageManager).when(mContext).getPackageManager();
|
||||
|
||||
mController = new RecentNotifyingAppsPreferenceController(
|
||||
mContext, mBackend, mAppState, null);
|
||||
mContext, mBackend, mAppState, mHost);
|
||||
when(mScreen.findPreference(anyString())).thenReturn(mCategory);
|
||||
|
||||
when(mScreen.findPreference(RecentNotifyingAppsPreferenceController.KEY_SEE_ALL))
|
||||
@@ -110,6 +116,7 @@ public class RecentNotifyingAppsPreferenceControllerTest {
|
||||
when(mScreen.findPreference(RecentNotifyingAppsPreferenceController.KEY_DIVIDER))
|
||||
.thenReturn(mDivider);
|
||||
when(mCategory.getContext()).thenReturn(mContext);
|
||||
when(mHost.getActivity()).thenReturn(mActivity);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settings.notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.NotificationManager.Policy;
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.settings.R;
|
||||
@@ -63,7 +64,7 @@ public class ZenModePreferenceControllerTest {
|
||||
ShadowApplication shadowApplication = ShadowApplication.getInstance();
|
||||
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
|
||||
mContext = shadowApplication.getApplicationContext();
|
||||
mController = new ZenModePreferenceController(mContext);
|
||||
mController = new ZenModePreferenceController(mContext, null);
|
||||
when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
|
||||
mSummaryBuilder = spy(new ZenModeSettings.SummaryBuilder(mContext));
|
||||
ReflectionHelpers.setField(mController, "mSummaryBuilder", mSummaryBuilder);
|
||||
@@ -76,16 +77,16 @@ public class ZenModePreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_preferenceEnabled_shouldSetSummary() {
|
||||
public void updateState_automaticRuleEnabled_shouldSetSummary() {
|
||||
when(mPreference.isEnabled()).thenReturn(true);
|
||||
|
||||
mController.updateState(mPreference);
|
||||
verify(mPreference).setSummary(mContext.getString(R.string.zen_mode_settings_summary_off));
|
||||
verify(mPreference).setSummary(mContext.getResources().getString(
|
||||
R.string.zen_mode_sound_summary_off));
|
||||
|
||||
doReturn(1).when(mSummaryBuilder).getEnabledAutomaticRulesCount();
|
||||
mController.updateState(mPreference);
|
||||
verify(mPreference).setSummary(mContext.getResources().getQuantityString(
|
||||
R.plurals.zen_mode_settings_summary_on, 1, 1));
|
||||
verify(mPreference).setSummary(mSummaryBuilder.getSoundSummary());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
|
||||
package com.android.settings.security.trustagent;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.R;
|
||||
@@ -50,8 +48,6 @@ public class ManageTrustAgentsPreferenceControllerTest {
|
||||
private TrustAgentManager mTrustAgentManager;
|
||||
@Mock
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
|
||||
private FakeFeatureFactory mFeatureFactory;
|
||||
private Context mContext;
|
||||
@@ -70,8 +66,6 @@ public class ManageTrustAgentsPreferenceControllerTest {
|
||||
mController = new ManageTrustAgentsPreferenceController(mContext);
|
||||
mPreference = new Preference(mContext);
|
||||
mPreference.setKey(mController.getPreferenceKey());
|
||||
when(mScreen.findPreference(mController.getPreferenceKey()))
|
||||
.thenReturn(mPreference);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -86,10 +80,10 @@ public class ManageTrustAgentsPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_isNotSecure_shouldDisablePreference() {
|
||||
public void updateState_isNotSecure_shouldDisablePreference() {
|
||||
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
|
||||
|
||||
mController.displayPreference(mScreen);
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isEnabled()).isFalse();
|
||||
assertThat(mPreference.getSummary())
|
||||
@@ -97,12 +91,12 @@ public class ManageTrustAgentsPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_isSecure_noTrustAgent_shouldShowGenericSummary() {
|
||||
public void updateState_isSecure_noTrustAgent_shouldShowGenericSummary() {
|
||||
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
|
||||
when(mTrustAgentManager.getActiveTrustAgents(mContext, mLockPatternUtils))
|
||||
.thenReturn(new ArrayList<>());
|
||||
|
||||
mController.displayPreference(mScreen);
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
assertThat(mPreference.getSummary())
|
||||
@@ -110,12 +104,12 @@ public class ManageTrustAgentsPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPreference_isSecure_hasTrustAgent_shouldShowDetailedSummary() {
|
||||
public void updateState_isSecure_hasTrustAgent_shouldShowDetailedSummary() {
|
||||
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
|
||||
when(mTrustAgentManager.getActiveTrustAgents(mContext, mLockPatternUtils))
|
||||
.thenReturn(Arrays.asList(new TrustAgentManager.TrustAgentComponentInfo()));
|
||||
|
||||
mController.displayPreference(mScreen);
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.isEnabled()).isTrue();
|
||||
assertThat(mPreference.getSummary())
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
package com.android.settings.wallpaper;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import com.android.settings.SubSettings;
|
||||
import com.android.settings.TestConfig;
|
||||
@@ -42,16 +44,16 @@ import org.robolectric.annotation.Implements;
|
||||
import org.robolectric.shadows.ShadowActivity;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
|
||||
shadows = {
|
||||
WallpaperSuggestionActivityTest.ShadowWallpaperManagerWrapper.class
|
||||
})
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class WallpaperSuggestionActivityTest {
|
||||
|
||||
@Mock
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
@Mock
|
||||
private Resources mResources;
|
||||
|
||||
private ActivityController<WallpaperSuggestionActivity> mController;
|
||||
|
||||
@Before
|
||||
@@ -72,6 +74,17 @@ public class WallpaperSuggestionActivityTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wallpaperServiceEnabled_no_shouldReturnFalse() {
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
when(mResources.getBoolean(
|
||||
com.android.internal.R.bool.config_enableWallpaperService)).thenReturn(false);
|
||||
|
||||
assertThat(WallpaperSuggestionActivity.isSuggestionComplete(mContext))
|
||||
.isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = WallpaperSuggestionActivityTest.ShadowWallpaperManagerWrapper.class)
|
||||
public void hasWallpaperSet_no_shouldReturnFalse() {
|
||||
ShadowWallpaperManagerWrapper.setWallpaperId(0);
|
||||
|
||||
@@ -80,6 +93,7 @@ public class WallpaperSuggestionActivityTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(shadows = WallpaperSuggestionActivityTest.ShadowWallpaperManagerWrapper.class)
|
||||
public void hasWallpaperSet_yes_shouldReturnTrue() {
|
||||
ShadowWallpaperManagerWrapper.setWallpaperId(100);
|
||||
|
||||
@@ -100,6 +114,15 @@ public class WallpaperSuggestionActivityTest {
|
||||
sWallpaperId = 0;
|
||||
}
|
||||
|
||||
public void __constructor__(Context context) {
|
||||
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public boolean isWallpaperServiceEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public int getWallpaperId(int which) {
|
||||
return sWallpaperId;
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.widget;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class SeekBarPreferenceTest {
|
||||
private static final int MAX = 75;
|
||||
private static final int MIN = 5;
|
||||
private static final int PROGRESS = 16;
|
||||
|
||||
private Context mContext;
|
||||
private SeekBarPreference mSeekBarPreference;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
|
||||
mSeekBarPreference = new SeekBarPreference(mContext);
|
||||
mSeekBarPreference.setMax(MAX);
|
||||
mSeekBarPreference.setMin(MIN);
|
||||
mSeekBarPreference.setProgress(PROGRESS);
|
||||
mSeekBarPreference.setPersistent(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaveAndRestoreInstanceState() {
|
||||
final Parcelable parcelable = mSeekBarPreference.onSaveInstanceState();
|
||||
|
||||
final SeekBarPreference preference = new SeekBarPreference(mContext);
|
||||
preference.onRestoreInstanceState(parcelable);
|
||||
|
||||
assertThat(preference.getMax()).isEqualTo(MAX);
|
||||
assertThat(preference.getMin()).isEqualTo(MIN);
|
||||
assertThat(preference.getProgress()).isEqualTo(PROGRESS);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.wifi;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -75,4 +77,9 @@ public class ConnectedAccessPointPreferenceTest {
|
||||
verify(mOnGearClickListener, never()).onGearClick(mConnectedAccessPointPreference);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWidgetLayoutPreference() {
|
||||
assertThat(mConnectedAccessPointPreference.getWidgetLayoutResource()).isEqualTo(
|
||||
R.layout.preference_widget_gear_no_bg);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user