Merge "Added a new broadcast receiver to handle Brzail channel 50 area info"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 37edca7..a606216 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1161,6 +1161,18 @@
</activity>
-->
+ <activity android:name="Settings$BackgroundCheckSummaryActivity"
+ android:label="@string/background_check_title"
+ android:taskAffinity=""
+ android:enabled="false">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.applications.BackgroundCheckSummary" />
+ </activity>
+
<activity android:name="Settings$LocationSettingsActivity"
android:label="@string/location_settings_title"
android:icon="@drawable/ic_settings_location"
@@ -1456,6 +1468,17 @@
</intent-filter>
</activity>
+ <!-- Note this must not be exported since it authenticates the given user -->
+ <activity android:name="ConfirmDeviceCredentialActivity$InternalActivity"
+ android:exported="false"
+ android:permission="android.permission.MANAGE_USERS"
+ android:theme="@android:style/Theme.NoDisplay">
+ <intent-filter android:priority="1">
+ <action android:name="android.app.action.CONFIRM_DEVICE_CREDENTIAL_WITH_USER" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
<activity android:name=".SetupRedactionInterstitial"
android:taskAffinity="com.android.wizard"
android:theme="@style/SetupWizardDisableAppStartingTheme"/>
@@ -2634,5 +2657,48 @@
android:value="com.android.settings.applications.WriteSettingsDetails" />
</activity>
+ <activity android:name="ShowAdminSupportDetailsDialog"
+ android:theme="@style/Transparent"
+ android:excludeFromRecents="true">
+
+ <intent-filter>
+ <action android:name="android.app.action.SHOW_ADMIN_SUPPORT_DETAILS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <!-- Conditional receivers, only enabled during silenced state, default off-->
+ <receiver
+ android:name=".dashboard.conditional.HotspotCondition$Receiver"
+ android:enabled="false">
+ <intent-filter>
+ <action android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
+ </intent-filter>
+ </receiver>
+
+ <receiver
+ android:name=".dashboard.conditional.AirplaneModeCondition$Receiver"
+ android:enabled="false">
+ <intent-filter>
+ <action android:name="android.intent.action.AIRPLANE_MODE" />
+ </intent-filter>
+ </receiver>
+
+ <receiver
+ android:name=".dashboard.conditional.DndCondition$Receiver"
+ android:enabled="false">
+ <intent-filter>
+ <action android:name="android.app.action.INTERRUPTION_FILTER_CHANGED_INTERNAL" />
+ </intent-filter>
+ </receiver>
+
+ <receiver
+ android:name=".dashboard.conditional.CellularDataCondition$Receiver"
+ android:enabled="false">
+ <intent-filter>
+ <action android:name="android.intent.action.ANY_DATA_STATE" />
+ </intent-filter>
+ </receiver>
+
</application>
</manifest>
diff --git a/res/drawable/ic_add_24dp.xml b/res/drawable/ic_add_24dp.xml
index 6535107..97178b2 100644
--- a/res/drawable/ic_add_24dp.xml
+++ b/res/drawable/ic_add_24dp.xml
@@ -14,11 +14,12 @@
~ limitations under the License
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="48.0"
- android:viewportHeight="48.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48"
+ android:tint="?android:attr/colorAccent">
<path
- android:fillColor="?android:attr/colorAccent"
- android:pathData="M38.0,26.0L26.0,26.0l0.0,12.0l-4.0,0.0L22.0,26.0L10.0,26.0l0.0,-4.0l12.0,0.0L22.0,10.0l4.0,0.0l0.0,12.0l12.0,0.0l0.0,4.0z"/>
+ android:fillColor="@android:color/white"
+ android:pathData="M38,26L26,26l0,12l-4,0L22,26L10,26l0,-4l12,0L22,10l4,0l0,12l12,0l0,4.0z"/>
</vector>
diff --git a/res/drawable/ic_airplane.xml b/res/drawable/ic_airplane.xml
new file mode 100644
index 0000000..b3e0ba0
--- /dev/null
+++ b/res/drawable/ic_airplane.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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:name="root"
+ android:alpha="1.0"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48" >
+ <group
+ android:name="ic_signal_airplane"
+ android:translateX="21.9995"
+ android:translateY="25.73401" >
+ <group
+ android:name="ic_signal_airplane_pivot"
+ android:translateX="-23.21545"
+ android:translateY="-18.86649" >
+ <clip-path
+ android:name="mask"
+ android:pathData="M 37.8337860107,-40.4599914551 c 0.0,0.0 -35.8077850342,31.5523681641 -35.8077850342,31.5523681641 c 0.0,0.0 9.55097961426,9.55285644531 9.55097961426,9.55285644531 c 0.0,0.0 -2.61698913574,2.09387207031 -2.61698913574,2.09387207031 c 0.0,0.0 -9.75096130371,-9.56428527832 -9.75096130371,-9.56428527832 c 0.0,0.0 -34.6200408936,25.4699249268 -34.6200408936,25.4699249268 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 73.2448120117,-59.1047973633 73.2448120117,-59.1047973633 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
+ <group
+ android:name="cross" >
+ <path
+ android:name="cross_1"
+ android:pathData="M 7.54049682617,3.9430847168 c 0.0,0.0 0.324981689453,0.399978637695 0.324981689453,0.399978637695 "
+ android:strokeColor="#FFFFFFFF"
+ android:strokeAlpha="0"
+ android:strokeWidth="3.5"
+ android:fillColor="#00000000" />
+ </group>
+ <group
+ android:name="plane"
+ android:translateX="23.481"
+ android:translateY="18.71151" >
+ <path
+ android:name="plane_1"
+ android:pathData="M 18.9439849854,7.98849487305 c 0.0,0.0 0.0,-4.0 0.0,-4.0 c 0.0,0.0 -16.0,-10.0 -16.0,-10.0 c 0.0,0.0 0.0,-11.0 0.0,-11.0 c 0.0,-1.70001220703 -1.30000305176,-3.0 -3.0,-3.0 c -1.69999694824,0.0 -3.0,1.29998779297 -3.0,3.0 c 0.0,0.0 0.0,11.0 0.0,11.0 c 0.0,0.0 -16.0,10.0 -16.0,10.0 c 0.0,0.0 0.0,4.0 0.0,4.0 c 0.0,0.0 16.0,-5.0 16.0,-5.0 c 0.0,0.0 0.0,11.0 0.0,11.0 c 0.0,0.0 -4.0,3.0 -4.0,3.0 c 0.0,0.0 0.0,3.0 0.0,3.0 c 0.0,0.0 7.0,-2.0 7.0,-2.0 c 0.0,0.0 7.0,2.0 7.0,2.0 c 0.0,0.0 0.0,-3.0 0.0,-3.0 c 0.0,0.0 -4.0,-3.0 -4.0,-3.0 c 0.0,0.0 0.0,-11.0 0.0,-11.0 c 0.0,0.0 16.0,5.0 16.0,5.0 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/res/drawable/ic_cellular_off.xml b/res/drawable/ic_cellular_off.xml
new file mode 100644
index 0000000..7840123
--- /dev/null
+++ b/res/drawable/ic_cellular_off.xml
@@ -0,0 +1,41 @@
+<!--
+Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
+ android:width="17dp"
+ android:height="17dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M8,9
+ l-2.87,-2.87
+ -2.87,2.87
+ -1.13,-1.13
+ 2.87,-2.87
+ -2.87,-2.87
+ 1.13,-1.13
+ 2.87,2.87
+ 2.87,-2.87
+ 1.13,1.13,
+ -2.87,2.87
+ 2.87,2.87
+ L8,9
+ z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M2.000000,22.000000l20.000000,0.000000 0.000000,-20.000000z"/>
+</vector>
diff --git a/res/drawable/ic_expand_less.xml b/res/drawable/ic_expand_less.xml
index 3a00faf..7ccc080 100644
--- a/res/drawable/ic_expand_less.xml
+++ b/res/drawable/ic_expand_less.xml
@@ -19,10 +19,11 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
- android:viewportHeight="24">
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorControlNormal">
<path
- android:fillColor="?android:attr/colorControlNormal"
+ android:fillColor="@android:color/white"
android:pathData="M12.0,8.0l-6.0,6.0 1.41,1.41L12.0,10.83l4.59,4.58L18.0,14.0z"/>
</vector>
diff --git a/res/drawable/ic_expand_more.xml b/res/drawable/ic_expand_more.xml
index 64d2242..609cf36 100644
--- a/res/drawable/ic_expand_more.xml
+++ b/res/drawable/ic_expand_more.xml
@@ -19,10 +19,11 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
- android:viewportHeight="24">
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorControlNormal">
<path
- android:fillColor="?android:attr/colorControlNormal"
+ android:fillColor="@android:color/white"
android:pathData="M16.59,8.59L12.0,13.17 7.41,8.59 6.0,10.0l6.0,6.0 6.0,-6.0z"/>
</vector>
diff --git a/res/drawable/ic_hotspot.xml b/res/drawable/ic_hotspot.xml
new file mode 100644
index 0000000..d8528dd
--- /dev/null
+++ b/res/drawable/ic_hotspot.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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:name="root"
+ android:alpha="1.0"
+ android:height="48dp"
+ android:width="48dp"
+ android:viewportHeight="48"
+ android:viewportWidth="48" >
+ <group
+ android:name="ic_hotspot"
+ android:translateX="23.9778"
+ android:translateY="24.26443" >
+ <group
+ android:name="ic_hotspot_pivot"
+ android:translateX="-23.21545"
+ android:translateY="-18.86649" >
+ <clip-path
+ android:name="mask"
+ android:pathData="M 38.8337860107,-40.3974914551 c 0.0,0.0 -38.4077911377,30.8523712158 -38.4077911377,30.8523712158 c 0.0,0.0 6.97125244141,7.33258056641 6.97125244141,7.33258056641 c 0.0,0.0 -2.4169921875,2.57838439941 -2.4169921875,2.57838439941 c 0.0,0.0 -6.77128601074,-6.82850646973 -6.77128601074,-6.82850646973 c 0.0,0.0 -32.6199798584,25.1699066162 -32.6199798584,25.1699066162 c 0.0,0.0 55.9664764404,69.742401123 55.9664764404,69.742401123 c 0.0,0.0 27.6589050293,-22.6579437256 27.6589050293,-22.6579437256 c 0.0,0.0 -30.8645172119,-34.00390625 -30.8645172119,-34.00390625 c 0.0,0.0 2.70756530762,-1.99278259277 2.70756530762,-1.99278259277 c 0.0,0.0 1.53030395508,-0.876571655273 1.53030395508,-0.876571655274 c 0.0,0.0 2.85780334473,-3.12069702148 2.85780334473,-3.12069702148 c 0.0,0.0 0.659332275391,0.664688110352 0.659332275391,0.664688110351 c 0.0,0.0 -3.13299560547,2.82977294922 -3.13299560547,2.82977294922 c 0.0,0.0 29.0108337402,34.4080963135 29.0108337402,34.4080963135 c 0.0,0.0 42.8175811768,-34.3554534912 42.8175811768,-34.3554534912 c 0.0,0.0 -55.9664916992,-69.7423400879 -55.9664916992,-69.7423400879 Z" />
+ <group
+ android:name="cross" >
+ <path
+ android:name="cross_1"
+ android:pathData="M 4.44044494629,2.24310302734 c 0.0,0.0 0.0875396728516,0.112457275391 0.0875396728516,0.112457275391 "
+ android:strokeColor="#FFFFFFFF"
+ android:strokeAlpha="0"
+ android:strokeWidth="3.5"
+ android:fillColor="#00000000" />
+ </group>
+ <group
+ android:name="hotspot"
+ android:translateX="23.481"
+ android:translateY="18.71151" >
+ <group
+ android:name="circles"
+ android:translateX="-0.23909"
+ android:translateY="-0.10807" >
+ <path
+ android:name="path_3"
+ android:pathData="M -0.0042724609375,-2.64895629883 c -2.20922851562,0.0 -4.0,1.791015625 -4.0,4.0 c 0.0,2.20922851562 1.79077148438,4.0 4.0,4.0 c 2.208984375,0.0 4.0,-1.79077148438 4.0,-4.0 c 0.0,-2.208984375 -1.791015625,-4.0 -4.0,-4.0 Z M 11.9957275391,1.35104370117 c 0.0,-6.626953125 -5.373046875,-12.0 -12.0,-12.0 c -6.62719726562,0.0 -12.0,5.373046875 -12.0,12.0 c 0.0,4.43603515625 2.41381835938,8.30004882812 5.99194335938,10.3771972656 c 0.0,0.0 2.01586914062,-3.48217773438 2.01586914062,-3.48217773438 c -2.38500976562,-1.38500976562 -4.0078125,-3.93798828125 -4.0078125,-6.89501953125 c 0.0,-4.41796875 3.58178710938,-8.0 8.0,-8.0 c 4.41796875,0.0 8.0,3.58203125 8.0,8.0 c 0.0,2.95703125 -1.623046875,5.51000976562 -4.00805664062,6.89501953125 c 0.0,0.0 2.01586914062,3.48217773438 2.01586914062,3.48217773438 c 3.578125,-2.0771484375 5.9921875,-5.94116210938 5.9921875,-10.3771972656 Z M -0.0042724609375,-18.6489562988 c -11.0451660156,0.0 -20.0,8.9541015625 -20.0,20.0 c 0.0,7.39306640625 4.02099609375,13.8330078125 9.98779296875,17.2951660156 c 0.0,0.0 2.00219726562,-3.458984375 2.00219726562,-3.458984375 c -4.77319335938,-2.77001953125 -7.98999023438,-7.92211914062 -7.98999023438,-13.8361816406 c 0.0,-8.8369140625 7.16381835938,-16.0 16.0,-16.0 c 8.83595275879,0.0 16.0000152588,7.1630859375 16.0000152588,16.0 c 0.0,5.9140625 -3.21704101562,11.0661621094 -7.990234375,13.8361816406 c 0.0,0.0 2.00219726562,3.458984375 2.00219726563,3.458984375 c 5.966796875,-3.46215820312 9.98803710937,-9.90209960938 9.98803710938,-17.2951660156 c 0.0,-11.0458984375 -8.955078125,-20.0 -20.0000152588,-20.0 Z"
+ android:fillColor="#FFFFFFFF"
+ android:fillAlpha="1" />
+ </group>
+ </group>
+ </group>
+ </group>
+</vector>
diff --git a/res/drawable/ic_info.xml b/res/drawable/ic_info.xml
index 13d00a4..6e19d26 100644
--- a/res/drawable/ic_info.xml
+++ b/res/drawable/ic_info.xml
@@ -14,11 +14,11 @@
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">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M11.0,17.0l2.0,0.0l0.0,-6.0l-2.0,0.0l0.0,6.0zm1.0,-15.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.41,0.0 -8.0,-3.59 -8.0,-8.0s3.59,-8.0 8.0,-8.0 8.0,3.59 8.0,8.0 -3.59,8.0 -8.0,8.0zM11.0,9.0l2.0,0.0L13.0,7.0l-2.0,0.0l0.0,2.0z"/>
+ android:fillColor="@android:color/white"
+ android:pathData="M11,17l2,0l0,-6l-2,0l0,6.0zm1,-15.0C6.48,2 2,6.48 2,12.0s4.48,10 10,10 10,-4.48 10,-10.0S17.52,2 12,2.0zm0,18.0c-4.41,0 -8,-3.59 -8,-8.0s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8.0zM11,9l2,0L13,7l-2,0l0,2.0z"/>
</vector>
diff --git a/res/drawable/ic_remove_24dp.xml b/res/drawable/ic_remove_24dp.xml
new file mode 100644
index 0000000..9233623
--- /dev/null
+++ b/res/drawable/ic_remove_24dp.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ Copyright (C) 2015 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="24dp"
+ android:height="24dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48"
+ android:tint="?android:attr/colorAccent">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M38 26H10v-4h28v4z"/>
+</vector>
diff --git a/res/drawable/ic_settings_lock_outline.xml b/res/drawable/ic_settings_lock_outline.xml
new file mode 100644
index 0000000..1c4202c
--- /dev/null
+++ b/res/drawable/ic_settings_lock_outline.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="22.0"
+ android:tint="?android:attr/colorAccent">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zM8.9 6c0-1.71 1.39-3.1 3.1-3.1s3.1 1.39 3.1 3.1v2H8.9V6zM18 20H6V10h12v10z" />
+</vector>
diff --git a/res/drawable/ic_zen.xml b/res/drawable/ic_zen.xml
new file mode 100644
index 0000000..17ecf21
--- /dev/null
+++ b/res/drawable/ic_zen.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2015 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:height="24dp"
+ android:viewportHeight="48.0"
+ android:viewportWidth="48.0"
+ android:width="24dp" >
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M24.0,4.0C12.95,4.0 4.0,12.95 4.0,24.0s8.95,20.0 20.0,20.0 20.0,-8.95 20.0,-20.0S35.05,4.0 24.0,4.0zm10.0,22.0L14.0,26.0l0.0,-4.0l20.0,0.0l0.0,4.0z" />
+
+</vector>
diff --git a/res/drawable/preference_highlight.xml b/res/drawable/preference_highlight.xml
index 20c1a0f..105ff18 100644
--- a/res/drawable/preference_highlight.xml
+++ b/res/drawable/preference_highlight.xml
@@ -19,4 +19,3 @@
<item android:id="@android:id/mask"
android:drawable="@android:color/white" />
</ripple>
-
diff --git a/res/drawable/screen_zoom_preview_action_background.xml b/res/drawable/screen_zoom_preview_action_background.xml
new file mode 100644
index 0000000..32fbb02
--- /dev/null
+++ b/res/drawable/screen_zoom_preview_action_background.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <size android:width="24dp"
+ android:height="24dp" />
+ <solid android:color="@android:color/white" />
+</shape>
diff --git a/res/layout/admin_support_details_dialog.xml b/res/layout/admin_support_details_dialog.xml
new file mode 100644
index 0000000..0d857df
--- /dev/null
+++ b/res/layout/admin_support_details_dialog.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/admin_details_dialog_padding"
+ android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:paddingBottom="@dimen/admin_details_dialog_padding">
+ <ImageView
+ android:layout_width="@dimen/admin_details_dialog_icon_size"
+ android:layout_height="@dimen/admin_details_dialog_icon_size"
+ android:src="@drawable/ic_settings_lock_outline"
+ android:scaleType="fitCenter"
+ android:contentDescription="@null" />
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/admin_details_dialog_padding"
+ android:text="@string/disabled_by_policy_title"
+ android:textAppearance="@android:style/TextAppearance.Material.Title" />
+ </LinearLayout>
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:fadeScrollbars="false">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <TextView android:id="@+id/disabled_by_admin_msg"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:textColor="?android:attr/textColorSecondary" />
+ <TextView android:id="@+id/admin_support_msg"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:textColor="?android:attr/textColorSecondary" />
+ <TextView android:id="@+id/admins_policies_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="@dimen/admin_details_dialog_link_padding_top"
+ android:text="@string/list_of_administrators"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:textColor="?android:attr/colorAccent"
+ android:clickable="true"
+ android:background="?android:attr/selectableItemBackground" />
+ </LinearLayout>
+ </ScrollView>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/app_ops_item.xml b/res/layout/app_ops_item.xml
index 8d21456..adba9da 100644
--- a/res/layout/app_ops_item.xml
+++ b/res/layout/app_ops_item.xml
@@ -25,7 +25,7 @@
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingTop="8dip"
android:paddingBottom="8dip"
- android:columnCount="3">
+ android:columnCount="4">
<ImageView
android:id="@+id/app_icon"
@@ -47,6 +47,14 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:textAlignment="viewStart" />
+ <Switch
+ android:id="@+id/op_switch"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_rowSpan="2"
+ android:focusable="false"
+ android:clickable="false" />
+
<TextView
android:id="@+id/op_name"
android:layout_width="0dip"
diff --git a/res/layout/background_check_summary.xml b/res/layout/background_check_summary.xml
new file mode 100644
index 0000000..ee47194
--- /dev/null
+++ b/res/layout/background_check_summary.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2015, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/appops_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+</LinearLayout>
diff --git a/res/layout/bugreport_options_dialog.xml b/res/layout/bugreport_options_dialog.xml
new file mode 100644
index 0000000..ac98d18
--- /dev/null
+++ b/res/layout/bugreport_options_dialog.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal" >
+
+ <CheckedTextView
+ android:id="@+id/bugreport_option_interactive_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:checked="true"
+ android:drawableStart="?android:attr/listChoiceIndicatorSingle"
+ android:ellipsize="marquee"
+ android:gravity="center_vertical"
+ android:paddingEnd="?android:attr/dialogPreferredPadding"
+ android:paddingStart="20dp"
+ android:text="@*android:string/bugreport_option_interactive_title"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorAlertDialogListItem" />
+
+ <TextView
+ android:id="@+id/bugreport_option_interactive_summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/bugreport_option_interactive_title"
+ android:maxLines="10"
+ android:paddingBottom="8dp"
+ android:paddingStart="52dp"
+ android:paddingEnd="?android:attr/dialogPreferredPadding"
+ android:text="@*android:string/bugreport_option_interactive_summary"
+ android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+ android:textColor="?android:attr/textColorSecondary" />
+
+ <CheckedTextView
+ android:id="@+id/bugreport_option_full_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/bugreport_option_interactive_summary"
+ android:checked="false"
+ android:drawableStart="?android:attr/listChoiceIndicatorSingle"
+ android:ellipsize="marquee"
+ android:gravity="center_vertical"
+ android:paddingEnd="?android:attr/dialogPreferredPadding"
+ android:paddingStart="20dp"
+ android:text="@*android:string/bugreport_option_full_title"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorAlertDialogListItem" />
+
+ <TextView
+ android:id="@+id/bugreport_option_full_summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/bugreport_option_full_title"
+ android:maxLines="10"
+ android:paddingBottom="8dp"
+ android:paddingStart="52dp"
+ android:paddingEnd="?android:attr/dialogPreferredPadding"
+ android:text="@*android:string/bugreport_option_full_summary"
+ android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+ android:textColor="?android:attr/textColorSecondary" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/condition_card.xml b/res/layout/condition_card.xml
new file mode 100644
index 0000000..482d5b6
--- /dev/null
+++ b/res/layout/condition_card.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:background="?android:attr/colorAccent"
+ android:elevation="3dp"
+ android:clickable="true">
+
+ <LinearLayout
+ android:id="@+id/collapsed_group"
+ android:layout_width="match_parent"
+ android:layout_height="56dp"
+ android:orientation="horizontal"
+ android:gravity="center">
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="24dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="36dp"
+ android:tint="?android:attr/textColorPrimaryInverse" />
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorPrimaryInverse" />
+
+ <ImageView
+ android:id="@+id/expand_indicator"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:tint="?android:attr/textColorPrimaryInverse"
+ android:padding="?android:attr/listPreferredItemPaddingEnd"
+ android:clickable="true"
+ android:background="?android:attr/selectableItemBackground" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/detail_group"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="60dp"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:paddingBottom="16dp"
+ android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+ android:textColor="?android:attr/textColorPrimaryInverse" />
+
+ <!-- TODO: Better background -->
+ <View
+ android:layout_width="match_parent"
+ android:layout_height=".25dp"
+ android:background="@android:color/white" />
+
+ <com.android.internal.widget.ButtonBarLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ style="?attr/buttonBarStyle"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+
+ <Button
+ android:id="@+id/first_action"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingStart="0dp"
+ android:textColor="?android:attr/textColorPrimaryInverse"
+ style="?android:attr/buttonBarButtonStyle" />
+
+ <Button
+ android:id="@+id/second_action"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="?android:attr/textColorPrimaryInverse"
+ style="?android:attr/buttonBarButtonStyle" />
+
+ </com.android.internal.widget.ButtonBarLayout>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/res/layout/dashboard.xml b/res/layout/dashboard.xml
index ae5be68..93261a53 100644
--- a/res/layout/dashboard.xml
+++ b/res/layout/dashboard.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
-<android.support.v7.widget.RecyclerView
+<com.android.settings.dashboard.conditional.FocusRecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dashboard_container"
android:layout_width="match_parent"
diff --git a/res/layout/fingerprint_enroll_find_sensor_base.xml b/res/layout/fingerprint_enroll_find_sensor_base.xml
index f65e932..3f69a0a 100644
--- a/res/layout/fingerprint_enroll_find_sensor_base.xml
+++ b/res/layout/fingerprint_enroll_find_sensor_base.xml
@@ -22,48 +22,50 @@
android:layout_height="match_parent"
style="?attr/fingerprint_layout_theme">
- <LinearLayout
- style="@style/SuwContentFrame"
+ <FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:clipToPadding="false"
android:clipChildren="false">
- <TextView
- style="@style/TextAppearance.FingerprintMessage"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/suw_description_margin_top"
- android:text="@string/security_settings_fingerprint_enroll_find_sensor_message"/>
-
- <View
- android:layout_height="0dp"
- android:layout_width="match_parent"
- android:layout_weight="1"/>
-
<include
layout="@layout/fingerprint_enroll_find_sensor_graphic"
- android:layout_width="@dimen/fingerprint_find_sensor_graphic_size"
- android:layout_height="@dimen/fingerprint_find_sensor_graphic_size"
- android:layout_gravity="center_horizontal"/>
-
- <View
- android:layout_height="0dp"
android:layout_width="match_parent"
- android:layout_weight="1"/>
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal|bottom"/>
- <Button
- style="@style/Button.FingerprintButton"
- android:id="@+id/next_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="4dp"
- android:layout_marginEnd="-12dp"
- android:layout_gravity="end"
- android:gravity="end|center_vertical"
- android:text="@string/fingerprint_enroll_button_next" />
+ <LinearLayout
+ style="@style/SuwContentFrame"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:clipToPadding="false"
+ android:clipChildren="false">
- </LinearLayout>
+ <TextView
+ style="@style/TextAppearance.FingerprintMessage"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/suw_description_margin_top"
+ android:text="@string/security_settings_fingerprint_enroll_find_sensor_message"/>
+ <View
+ android:layout_height="0dp"
+ android:layout_width="match_parent"
+ android:layout_weight="1"/>
+
+ <Button
+ style="@style/Button.FingerprintButton"
+ android:id="@+id/next_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:layout_marginEnd="-12dp"
+ android:layout_gravity="end"
+ android:gravity="end|center_vertical"
+ android:text="@string/fingerprint_enroll_button_next" />
+
+ </LinearLayout>
+ </FrameLayout>
</com.android.setupwizardlib.SetupWizardLayout>
diff --git a/res/layout/preference_importance_slider.xml b/res/layout/preference_importance_slider.xml
new file mode 100644
index 0000000..737254b
--- /dev/null
+++ b/res/layout/preference_importance_slider.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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:gravity="center_vertical"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:orientation="vertical"
+ android:clickable="false"
+ android:focusable="false"
+ android:paddingTop="8dip"
+ android:paddingBottom="8dip">
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:textColor="?android:attr/textColorPrimary"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal" />
+
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignStart="@android:id/title"
+ android:textAlignment="viewStart"
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary"
+ android:maxLines="10"
+ android:minLines="2" />
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="6dp">
+
+ <ImageView
+ android:id="@+id/low_importance"
+ android:src="@android:drawable/ic_menu_close_clear_cancel"
+ android:layout_gravity="center_vertical|start"
+ android:layout_width="24dp"
+ android:layout_height="24dp" />
+
+ <SeekBar
+ android:id="@*android:id/seekbar"
+ android:layout_marginStart="24dp"
+ android:layout_marginEnd="24dp"
+ android:layout_gravity="center_vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:focusable="true"/>
+
+ <ImageView
+ android:id="@+id/max_importance"
+ android:src="@android:drawable/ic_popup_reminder"
+ android:layout_gravity="center_vertical|end"
+ android:layout_width="24dp"
+ android:layout_height="24dp" />
+
+ </FrameLayout>
+
+</LinearLayout>
diff --git a/res/layout/preference_volume_slider.xml b/res/layout/preference_volume_slider.xml
index 878a710..d279eb6 100644
--- a/res/layout/preference_volume_slider.xml
+++ b/res/layout/preference_volume_slider.xml
@@ -20,7 +20,8 @@
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:clickable="false" >
<LinearLayout
android:layout_width="match_parent"
diff --git a/res/layout/radio_info.xml b/res/layout/radio_info.xml
index a288224..16bf0f6 100644
--- a/res/layout/radio_info.xml
+++ b/res/layout/radio_info.xml
@@ -51,13 +51,13 @@
/>
<LinearLayout style="@style/entry_layout">
- <TextView android:text="@string/radio_info_ping_ipaddr" style="@style/info_label" />
- <TextView android:id="@+id/pingIpAddr" style="@style/info_value" />
+ <TextView android:text="@string/radio_info_ping_hostname_v4" style="@style/info_label" />
+ <TextView android:id="@+id/pingHostnameV4" style="@style/info_value" />
</LinearLayout>
<LinearLayout style="@style/entry_layout">
- <TextView android:text="@string/radio_info_ping_hostname" style="@style/info_label" />
- <TextView android:id="@+id/pingHostname" style="@style/info_value" />
+ <TextView android:text="@string/radio_info_ping_hostname_v6" style="@style/info_label" />
+ <TextView android:id="@+id/pingHostnameV6" style="@style/info_value" />
</LinearLayout>
<LinearLayout style="@style/entry_layout">
@@ -71,6 +71,14 @@
<TextView android:id="@+id/dbm" style="@style/info_value" />
</LinearLayout>
+ <!-- CellInfoListRate -->
+ <Button android:id="@+id/cell_info_list_rate"
+ android:textSize="14sp"
+ android:layout_marginTop="8dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ />
+
<!-- Location -->
<LinearLayout style="@style/entry_layout">
<TextView android:text="@string/radio_info_signal_location_label" style="@style/info_label" />
@@ -88,6 +96,8 @@
<LinearLayout style="@style/entry_layout">
<TextView android:text="@string/radio_info_cellinfo_label"
style="@style/info_label" />
+ </LinearLayout>
+ <LinearLayout style="@style/entry_layout">
<TextView android:id="@+id/cellinfo" style="@style/info_value" />
</LinearLayout>
@@ -140,7 +150,6 @@
<TextView android:id="@+id/call" style="@style/info_value" />
</LinearLayout>
-
<!-- Radio Resets -->
<LinearLayout style="@style/entry_layout">
<TextView android:text="@string/radio_info_radio_resets_label" style="@style/info_label" />
@@ -210,15 +219,7 @@
android:layout_height="wrap_content"
/>
- <!-- CellInfoListRate -->
- <Button android:id="@+id/cell_info_list_rate"
- android:textSize="14sp"
- android:layout_marginTop="8dip"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
-
- <!-- IMS registration required -->
+ <!-- IMS registration required -->
<Button android:id="@+id/ims_reg_required"
android:textSize="14sp"
android:layout_marginTop="8dip"
diff --git a/res/layout/screen_zoom_activity.xml b/res/layout/screen_zoom_activity.xml
new file mode 100644
index 0000000..81ce102
--- /dev/null
+++ b/res/layout/screen_zoom_activity.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="16dp"
+ android:paddingLeft="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/screen_zoom_summary"
+ android:layout_marginBottom="16dp"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead" />
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/screen_zoom_preview_height"
+ android:background="?android:attr/colorBackgroundFloating"
+ android:elevation="2dp">
+
+ <com.android.settings.display.TouchBlockingFrameLayout
+ android:id="@+id/preview_frame"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <TextView
+ android:id="@+id/current_density"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal|bottom"
+ android:padding="8dp"
+ android:theme="@android:style/Theme.Material"
+ android:background="?android:attr/colorBackgroundFloating"
+ android:textAppearance="@android:style/TextAppearance.Material.Caption"
+ android:textAllCaps="true"
+ android:elevation="2dp" />
+ </FrameLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="8dp">
+
+ <ImageView
+ android:id="@+id/smaller"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:src="@drawable/ic_remove_24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:tintMode="src_in"
+ android:scaleType="center"
+ android:focusable="true"
+ android:contentDescription="@string/screen_zoom_make_smaller_desc" />
+
+ <SeekBar
+ android:id="@+id/seek_bar"
+ android:layout_width="0dp"
+ android:layout_height="48dp"
+ android:layout_weight="1" />
+
+ <ImageView
+ android:id="@+id/larger"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:background="?android:attr/selectableItemBackgroundBorderless"
+ android:src="@drawable/ic_add_24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:tintMode="src_in"
+ android:scaleType="center"
+ android:focusable="true"
+ android:contentDescription="@string/screen_zoom_make_larger_desc" />
+ </LinearLayout>
+ </LinearLayout>
+</ScrollView>
diff --git a/res/layout/screen_zoom_preview.xml b/res/layout/screen_zoom_preview.xml
new file mode 100644
index 0000000..7cdb663
--- /dev/null
+++ b/res/layout/screen_zoom_preview.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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="match_parent"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/actionBarSize"
+ android:orientation="horizontal"
+ android:theme="?android:attr/actionBarTheme"
+ style="?android:attr/actionBarStyle">
+
+ <TextView
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginLeft="16dp"
+ android:text="@string/screen_zoom_preview_title"
+ android:textAppearance="@android:style/TextAppearance.Material.Widget.ActionBar.Title" />
+
+ <ImageView
+ android:layout_width="36dp"
+ android:layout_height="48dp"
+ style="?android:attr/actionOverflowButtonStyle" />
+ </LinearLayout>
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scrollbars="none"
+ android:background="?android:attr/colorBackgroundFloating">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <TextView
+ style="@android:style/TextAppearance.Material.Subhead"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="16dp"
+ android:layout_marginTop="16dp"
+ android:text="@string/permissions_label" />
+
+ <include layout="@layout/screen_zoom_preview_item" />
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_marginLeft="62dp"
+ android:layout_marginRight="8dp"
+ android:background="#36000000" />
+
+ <include layout="@layout/screen_zoom_preview_item" />
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_marginLeft="62dp"
+ android:layout_marginRight="8dp"
+ android:background="#36000000" />
+
+ <include layout="@layout/screen_zoom_preview_item" />
+
+ </LinearLayout>
+
+ </ScrollView>
+</LinearLayout>
diff --git a/res/layout/screen_zoom_preview_item.xml b/res/layout/screen_zoom_preview_item.xml
new file mode 100644
index 0000000..68076f0
--- /dev/null
+++ b/res/layout/screen_zoom_preview_item.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:padding="16dp"
+ tools:showIn="@layout/screen_zoom_preview">
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:background="@drawable/screen_zoom_preview_action_background"
+ android:backgroundTint="?android:attr/colorAccent"
+ android:src="@drawable/ic_settings_32dp"
+ android:scaleType="center" />
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingStart="16dp">
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/usage_access"
+ style="@android:style/TextAppearance.Material.Body1" />
+
+ <TextView
+ android:id="@+id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/usage_access_description"
+ style="@android:style/TextAppearance.Material.Caption" />
+ </LinearLayout>
+
+ <ImageView
+ android:id="@+id/action"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_marginLeft="24dp"
+ android:src="@drawable/ic_info"
+ android:tint="?android:attr/colorControlNormal"
+ android:tintMode="src_in"
+ android:scaleType="center" />
+</LinearLayout>
diff --git a/res/layout/wifi_status_test.xml b/res/layout/wifi_status_test.xml
index 2bdfbfc..aac3207 100644
--- a/res/layout/wifi_status_test.xml
+++ b/res/layout/wifi_status_test.xml
@@ -111,11 +111,6 @@
/>
<LinearLayout style="@style/entry_layout">
- <TextView android:text="@string/radio_info_ping_ipaddr" style="@style/info_label" />
- <TextView android:id="@+id/pingIpAddr" style="@style/info_value" />
- </LinearLayout>
-
- <LinearLayout style="@style/entry_layout">
<TextView android:text="@string/radio_info_ping_hostname" style="@style/info_label" />
<TextView android:id="@+id/pingHostname" style="@style/info_value" />
</LinearLayout>
diff --git a/res/raw/fingerprint_location_animation.mp4 b/res/raw/fingerprint_location_animation.mp4
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/res/raw/fingerprint_location_animation.mp4
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index d15c254..7612c97 100755
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -48,4 +48,7 @@
<!-- Fingerprint -->
<item name="fingerprint_illustration_aspect_ratio" format="float" type="dimen">0.0</item>
<dimen name="fingerprint_decor_padding_top">24dp</dimen>
+
+ <!-- Display, Screen zoom -->
+ <dimen name="screen_zoom_preview_height">160dp</dimen>
</resources>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index b3e2655..12a0172 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -620,11 +620,25 @@
<item>monitor high power location</item>
<item>get usage stats</item>
<item>mute/unmute microphone</item>
+ <item>show toast</item>
<item>project media</item>
<item>activate VPN</item>
<item>write wallpaper</item>
<item>assist structure</item>
<item>assist screenshot</item>
+ <item>read phone state</item>
+ <item>add voicemail</item>
+ <item>use sip</item>
+ <item>process outgoing call</item>
+ <item>fingerprint</item>
+ <item>body sensors</item>
+ <item>read cell broadcasts</item>
+ <item>mock location</item>
+ <item>read storage</item>
+ <item>write storage</item>
+ <item>turn on screen</item>
+ <item>get accounts</item>
+ <item>run in background</item>
</string-array>
<!-- User display names for app ops codes -->
@@ -674,11 +688,25 @@
<item>Location</item>
<item>Get usage stats</item>
<item>Mute/unmute microphone</item>
+ <item>Show toast</item>
<item>Project media</item>
<item>Activate VPN</item>
<item>Write wallpaper</item>
<item>Assist structure</item>
<item>Assist screenshot</item>
+ <item>Read phone state</item>
+ <item>Add voicemail</item>
+ <item>Use sip</item>
+ <item>Process outgoing call</item>
+ <item>Fingerprint</item>
+ <item>Body sensors</item>
+ <item>Read cell broadcasts</item>
+ <item>Mock location</item>
+ <item>Read storage</item>
+ <item>Write storage</item>
+ <item>Turn on screen</item>
+ <item>Get accounts</item>
+ <item>Run in background</item>
</string-array>
<!-- Titles for the list of long press timeout options. -->
@@ -880,237 +908,6 @@
<item>-1</item>
</integer-array>
- <!-- Titles for logd limit size selection preference. [CHAR LIMIT=14] -->
- <string-array name="select_logd_size_titles">
- <item>64K</item>
- <item>256K</item>
- <item>1M</item>
- <item>4M</item>
- <item>16M</item>
- </string-array>
-
- <!-- Titles for logd limit size lowram selection preference. [CHAR LIMIT=14] -->
- <string-array name="select_logd_size_lowram_titles">
- <item>64K</item>
- <item>256K</item>
- <item>1M</item>
- </string-array>
-
- <!-- Values for logd limit size selection preference. -->
- <string-array name="select_logd_size_values" translatable="false" >
- <item>65536</item>
- <item>262144</item>
- <item>1048576</item>
- <item>4194304</item>
- <item>16777216</item>
- </string-array>
-
- <!-- Summaries for logd limit size selection preference. [CHAR LIMIT=30]-->
- <string-array name="select_logd_size_summaries" >
- <item>64K per log buffer</item>
- <item>256K per log buffer</item>
- <item>1M per log buffer</item>
- <item>4M per log buffer</item>
- <item>16M per log buffer</item>
- </string-array>
-
- <!-- Titles for HDCP checking preference. [CHAR LIMIT=35] -->
- <string-array name="hdcp_checking_titles">
- <item>Never check</item>
- <item>Check for DRM content only</item>
- <item>Always check</item>
- </string-array>
-
- <!-- Values for HDCP checking preference. -->
- <string-array name="hdcp_checking_values" translatable="false" >
- <item>never</item>
- <item>drm-only</item>
- <item>always</item>
- </string-array>
-
- <!-- Summaries for HDCP checking preference. [CHAR LIMIT=100]-->
- <string-array name="hdcp_checking_summaries" >
- <item>Never use HDCP checking</item>
- <item>Use HDCP checking for DRM content only</item>
- <item>Always use HDCP checking</item>
- </string-array>
-
- <!-- Titles for window animation scale preference. [CHAR LIMIT=35] -->
- <string-array name="window_animation_scale_entries">
- <item>Animation off</item>
- <item>Animation scale .5x</item>
- <item>Animation scale 1x</item>
- <item>Animation scale 1.5x</item>
- <item>Animation scale 2x</item>
- <item>Animation scale 5x</item>
- <item>Animation scale 10x</item>
- </string-array>
-
- <!-- Values for window animation scale preference. -->
- <string-array name="window_animation_scale_values" translatable="false" >
- <item>0</item>
- <item>.5</item>
- <item>1</item>
- <item>1.5</item>
- <item>2</item>
- <item>5</item>
- <item>10</item>
- </string-array>
-
- <!-- Titles for transition animation scale preference. [CHAR LIMIT=35] -->
- <string-array name="transition_animation_scale_entries">
- <item>Animation off</item>
- <item>Animation scale .5x</item>
- <item>Animation scale 1x</item>
- <item>Animation scale 1.5x</item>
- <item>Animation scale 2x</item>
- <item>Animation scale 5x</item>
- <item>Animation scale 10x</item>
- </string-array>
-
- <!-- Values for transition animation scale preference. -->
- <string-array name="transition_animation_scale_values" translatable="false" >
- <item>0</item>
- <item>.5</item>
- <item>1</item>
- <item>1.5</item>
- <item>2</item>
- <item>5</item>
- <item>10</item>
- </string-array>
-
- <!-- Titles for animator duration scale preference. [CHAR LIMIT=35] -->
- <string-array name="animator_duration_scale_entries">
- <item>Animation off</item>
- <item>Animation scale .5x</item>
- <item>Animation scale 1x</item>
- <item>Animation scale 1.5x</item>
- <item>Animation scale 2x</item>
- <item>Animation scale 5x</item>
- <item>Animation scale 10x</item>
- </string-array>
-
- <!-- Values for animator duration scale preference. -->
- <string-array name="animator_duration_scale_values" translatable="false" >
- <item>0</item>
- <item>.5</item>
- <item>1</item>
- <item>1.5</item>
- <item>2</item>
- <item>5</item>
- <item>10</item>
- </string-array>
-
- <!-- Titles for overlay display devices preference. [CHAR LIMIT=35] -->
- <string-array name="overlay_display_devices_entries">
- <item>None</item>
- <item>480p</item>
- <item>480p (secure)</item>
- <item>720p</item>
- <item>720p (secure)</item>
- <item>1080p</item>
- <item>1080p (secure)</item>
- <item>4K</item>
- <item>4K (secure)</item>
- <item>4K (upscaled)</item>
- <item>4K (upscaled, secure)</item>
- <item>720p, 1080p (dual screen)</item>
- </string-array>
-
- <!-- Values for overlay display devices preference. -->
- <string-array name="overlay_display_devices_values" translatable="false" >
- <item></item>
- <item>720x480/142</item>
- <item>720x480/142,secure</item>
- <item>1280x720/213</item>
- <item>1280x720/213,secure</item>
- <item>1920x1080/320</item>
- <item>1920x1080/320,secure</item>
- <item>3840x2160/320</item>
- <item>3840x2160/320,secure</item>
- <item>1920x1080/320|3840x2160/640</item>
- <item>1920x1080/320|3840x2160/640,secure</item>
- <item>1280x720/213;1920x1080/320</item>
- </string-array>
-
- <!-- Titles for OpenGL traces preference. [CHAR LIMIT=35] -->
- <string-array name="enable_opengl_traces_entries">
- <item>None</item>
- <item>Logcat</item>
- <item>Systrace (Graphics)</item>
- <item>Call stack on glGetError</item>
- </string-array>
-
- <!-- Values for OpenGL traces preference. -->
- <string-array name="enable_opengl_traces_values" translatable="false" >
- <item>0</item>
- <item>1</item>
- <item>systrace</item>
- <item>error</item>
- </string-array>
-
- <!-- Titles for non-rectangular clipping preference. [CHAR LIMIT=35] -->
- <string-array name="show_non_rect_clip_entries">
- <item>Off</item>
- <item>Draw non-rectangular clip region in blue</item>
- <item>Highlight tested drawing commands in green</item>
- </string-array>
-
- <!-- Values for non-rectangular clipping preference. -->
- <string-array name="show_non_rect_clip_values" translatable="false" >
- <item>hide</item>
- <item>region</item>
- <item>highlight</item>
- </string-array>
-
- <!-- Titles for frame time tracking preference. [CHAR LIMIT=35] -->
- <string-array name="track_frame_time_entries">
- <item>Off</item>
- <item>On screen as bars</item>
- <item>In adb shell dumpsys gfxinfo</item>
- </string-array>
-
- <!-- Values for frame time tracking preference. -->
- <string-array name="track_frame_time_values" translatable="false" >
- <item>false</item>
- <item>visual_bars</item>
- <item>true</item>
- </string-array>
-
- <!-- Titles for debug overdraw preference. [CHAR LIMIT=50] -->
- <string-array name="debug_hw_overdraw_entries">
- <item>Off</item>
- <item>Show overdraw areas</item>
- <item>Show areas for Deuteranomaly</item>
- </string-array>
-
- <!-- Values for debug overdraw preference. -->
- <string-array name="debug_hw_overdraw_values" translatable="false" >
- <item>false</item>
- <item>show</item>
- <item>show_deuteranomaly</item>
- </string-array>
-
- <!-- Titles for app process limit preference. [CHAR LIMIT=35] -->
- <string-array name="app_process_limit_entries">
- <item>Standard limit</item>
- <item>No background processes</item>
- <item>At most 1 process</item>
- <item>At most 2 processes</item>
- <item>At most 3 processes</item>
- <item>At most 4 processes</item>
- </string-array>
-
- <!-- Values for app process limit preference. -->
- <string-array name="app_process_limit_values" translatable="false" >
- <item>-1</item>
- <item>0</item>
- <item>1</item>
- <item>2</item>
- <item>3</item>
- <item>4</item>
- </string-array>
-
<!-- Match this with the constants in VpnProfile. --> <skip />
<!-- Short names for each VPN type, not really translatable. [CHAR LIMIT=20] -->
<string-array name="vpn_types" translatable="false">
@@ -1213,24 +1010,6 @@
<item>13</item>
</string-array>
- <!-- Display color space adjustment modes for developers -->
- <string-array name="simulate_color_space_entries" translatable="false">
- <item>@string/daltonizer_mode_disabled</item>
- <item>@string/daltonizer_mode_monochromacy</item>
- <item>@string/daltonizer_mode_deuteranomaly</item>
- <item>@string/daltonizer_mode_protanomaly</item>
- <item>@string/daltonizer_mode_tritanomaly</item>
- </string-array>
-
- <!-- Values for display color space adjustment modes for developers -->
- <string-array name="simulate_color_space_values" translatable="false">
- <item>-1</item>
- <item>0</item>
- <item>2</item>
- <item>1</item>
- <item>3</item>
- </string-array>
-
<!-- Battery saver mode: allowable trigger threshold levels. -->
<integer-array name="battery_saver_trigger_values" translatable="false" >
<item>0</item>
@@ -1274,56 +1053,4 @@
<item>Red</item>
</string-array>
- <!-- USB configuration names for Developer Settings.
- This can be overridden by devices with additional USB configurations. -->
- <string-array name="usb_configuration_titles">
- <item>@string/usb_use_charging_only</item>
- <item>MTP (Media Transfer Protocol)</item>
- <item>PTP (Picture Transfer Protocol)</item>
- <item>RNDIS (USB Ethernet)</item>
- <item>Audio Source</item>
- <item>MIDI</item>
- </string-array>
-
- <!-- USB configuration values for Developer Settings.
- These are lists of USB functions passed to the USB Manager to change USB configuraton.
- This can be overridden by devices with additional USB configurations.
- Do not translate. -->
- <string-array name="usb_configuration_values" translatable="false">
- <!-- Do not translate. -->
- <item>none</item>
- <!-- Do not translate. -->
- <item>mtp</item>
- <!-- Do not translate. -->
- <item>ptp</item>
- <!-- Do not translate. -->
- <item>rndis</item>
- <!-- Do not translate. -->
- <item>audio_source</item>
- <!-- Do not translate. -->
- <item>midi</item>
- </string-array>
-
- <!-- Possible values for user theme in Display Settings.
- Do not translate. -->
- <string-array name="night_mode_entries" translatable="false">
- <!-- Do not translate. -->
- <item>@string/night_mode_no</item>
- <!-- Do not translate. -->
- <item>@string/night_mode_yes</item>
- <!-- Do not translate. -->
- <item>@string/night_mode_auto</item>
- </string-array>
-
- <!-- These values should match up with the MODE_NIGHT constants in UiModeManager.
- Do not translate. -->
- <string-array name="night_mode_values" translatable="false">
- <!-- Do not translate. -->
- <item>1</item>
- <!-- Do not translate. -->
- <item>2</item>
- <!-- Do not translate. -->
- <item>0</item>
- </string-array>
-
</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 62c34ea..5d7758b 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -110,8 +110,7 @@
<attr name="confirmDeviceCredentialsSideMargin" format="dimension" />
<attr name="confirmDeviceCredentialsTopMargin" format="dimension" />
- <declare-styleable name="DropDownPreference">
- <attr name="android:entries" />
- <attr name="android:entryValues" />
+ <declare-styleable name="RestrictedPreference">
+ <attr name="userRestriction" format="string"/>
</declare-styleable>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index dc0b186..539dc05 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -101,7 +101,7 @@
<dimen name="dashboard_category_padding_end">0dp</dimen>
<!-- Dashboard category panel elevation -->
- <dimen name="dashboard_category_elevation">4dp</dimen>
+ <dimen name="dashboard_category_elevation">2dp</dimen>
<!-- Dashboard category title layout height -->
<dimen name="dashboard_category_title_height">48dp</dimen>
@@ -250,6 +250,18 @@
<dimen name="shortcut_size">40dp</dimen>
<dimen name="badge_size">10dp</dimen>
+ <!-- Lock icon for preferences locked by admin -->
+ <dimen name="restricted_lock_icon_size">16dp</dimen>
+ <dimen name="restricted_lock_icon_padding">4dp</dimen>
+
+ <!-- Admin support contact details dialog. -->
+ <dimen name="admin_details_dialog_padding">24dp</dimen>
+ <dimen name="admin_details_dialog_icon_size">48dp</dimen>
+ <dimen name="admin_details_dialog_link_padding_top">36dp</dimen>
+
<!-- Button bar padding for unmount button. -->
<dimen name="unmount_button_padding">8dp</dimen>
+
+ <!-- Display, Screen zoom -->
+ <dimen name="screen_zoom_preview_height">240dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ecc465e..9d2f1f0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -403,7 +403,7 @@
<string name="radio_info_data_attempts_label">Data attempts:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
- <string name="radio_info_gprs_service_label">GPRS service:</string>
+ <string name="radio_info_gprs_service_label">Data Technology:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radio_info_roaming_label">Roaming:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
@@ -421,7 +421,7 @@
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radio_info_ppp_received_label">PPP received:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
- <string name="radio_info_gsm_service_label">GSM service:</string>
+ <string name="radio_info_gsm_service_label">Voice Technology:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radio_info_signal_strength_label">Signal strength:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
@@ -441,9 +441,9 @@
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radio_info_set_perferred_label">Set preferred network type:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
- <string name="radio_info_ping_ipaddr">Ping IpAddr:</string>
+ <string name="radio_info_ping_hostname_v4">Ping Hostname(www.google.com) IPv4:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
- <string name="radio_info_ping_hostname">Ping Hostname(www.google.com):</string>
+ <string name="radio_info_ping_hostname_v6">Ping Hostname(www.google.com) IPv6:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radio_info_http_client_test">HTTP Client test:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
@@ -1486,6 +1486,8 @@
<string name="wifi_menu_scan">Scan</string>
<!-- Menu option to Wi-Fi advanced settings -->
<string name="wifi_menu_advanced">Advanced</string>
+ <!-- Menu option to Wi-Fi configure settings -->
+ <string name="wifi_menu_configure">Configure</string>
<!-- Menu option to connect to a Wi-Fi network -->
<string name="wifi_menu_connect">Connect to network</string>
<!-- Menu option to remember a temporary Wi-Fi network -->
@@ -1656,6 +1658,8 @@
<string name="wifi_saved_access_points_titlebar">Saved networks</string>
<!-- Wi-Fi settings screen, advanced, settings section. This is a header shown above advanced wifi settings. [CHAR LIMIT=30] -->
<string name="wifi_advanced_titlebar">Advanced Wi\u2011Fi</string>
+ <!-- Wi-Fi settings screen, configure, settings section. This is a header shown above configure wifi settings. [CHAR LIMIT=30] -->
+ <string name="wifi_configure_titlebar">Configure Wi\u2011Fi</string>
<!-- Wi-Fi settings screen, setting title for setting the band [CHAR LIMIT=50]-->
<string name="wifi_setting_frequency_band_title">Wi\u2011Fi frequency band</string>
<!-- Wi-Fi settings screen, setting summary for setting the wifi frequency band [CHAR LIMIT=50]-->
@@ -1998,33 +2002,6 @@
<string name="auto_brightness_title">Adaptive brightness</string>
<!-- Sound & display settings screen, setting option summary to enable adaptive brightness [CHAR LIMIT=100] -->
<string name="auto_brightness_summary">Optimize brightness level for available light</string>
- <!-- Sound & display settings screen, setting option name to change the user interface theme [CHAR LIMIT=30] -->
- <string name="night_mode_title">Night mode</string>
- <!-- Sound & display settings screen, setting option summary to change the user interface theme [CHAR LIMIT=100] -->
- <string name="night_mode_summary">%s</string>
- <!-- Sound & display settings screen, theme setting value to prefer a light-colored user interface [CHAR LIMIT=30] -->
- <string name="night_mode_no">Disabled</string>
- <!-- Sound & display settings screen, theme setting value to prefer a dark-colored user interface [CHAR LIMIT=30] -->
- <string name="night_mode_yes">Always on</string>
- <!-- Sound & display settings screen, theme setting value to automatically switch between a light- or dark-colored user interface [CHAR LIMIT=30] -->
- <string name="night_mode_auto">Automatic</string>
-
- <!-- Developer settings screen, convert userdata to file encryption option name -->
- <string name="convert_to_file_encryption">Convert to file encryption</string>
- <!-- Developer settings screen, convert userdata to file encryption summary when option is available -->
- <string name="convert_to_file_encryption_enabled">Convert\u2026</string>
- <!-- Developer settings screen, convert userdata to file encryption summary when option is already done -->
- <string name="convert_to_file_encryption_done">Already file encrypted</string>
- <!-- Title used on dialog with final prompt for converting to file encryption -->
- <string name="title_convert_fbe">Converting to file based encryption</string>
- <!-- Warning displayed on dialog with final prompt for converting to file encryption -->
- <string name="convert_to_fbe_warning">
- Convert data partition to file based encryption.\n
- !!Warning!! This will erase all your data.\n
- This feature is alpha, and may not work correctly.\n
- Press \'Wipe and convert\u2026\' to continue.</string>
- <!-- Button on dialog that triggers convertion to file encryption -->
- <string name="button_convert_fbe">Wipe and convert\u2026</string>
<!-- Sound & display settings screen, setting option name to change screen timeout -->
<string name="screen_timeout">Sleep</string>
@@ -2806,8 +2783,6 @@
<!-- Security & location settings screen, section header for settings relating to location -->
<string name="location_title">My Location</string>
- <!-- Title for managed profile preference category [CHAR_LIMIT=25] -->
- <string name="managed_profile_location_category">Work profile</string>
<!-- [CHAR LIMIT=30] Title for managed profile location switch -->
<string name="managed_profile_location_switch_title">Location for work profile</string>
<!-- [CHAR LIMIT=30] Text to show on managed profile location switch if MDM has locked down location access for managed profile-->
@@ -3325,10 +3300,6 @@
<!-- Services settings screen, setting option summary for the user to go to the screen to app storage use -->
<string name="storageuse_settings_summary">View storage used by apps</string>
- <!-- Services settings screen, setting option name for the user to go to the screen to view running services -->
- <string name="runningservices_settings_title">Running services</string>
- <!-- Services settings screen, setting option summary for the user to go to the screen to view running services -->
- <string name="runningservices_settings_summary">View and control currently running services</string>
<!-- Label for a service item when it is restarting -->
<string name="service_restarting">Restarting</string>
<!-- Label for a process item representing a background process -->
@@ -3591,140 +3562,6 @@
<!-- Summary for built-in keyboard settings -->
<string name="builtin_keyboard_settings_summary">Physical keyboard settings</string>
- <!-- Development Settings. the title for the item to take the user to Development settings. Development settings are settings meant for application developers. -->
- <string name="development_settings_title">Developer options</string>
- <!-- Development Settings summary. The summary of the item to take the user to Development settings. Development settings are settings meant for application developers. -->
- <string name="development_settings_summary">Set options for app development</string>
- <!-- Setting checkbox title for Whether to enable USB debugging support on the phone. -->
- <!-- Error message for users that aren't allowed to modify developer options [CHAR LIMIT=none] -->
- <string name="development_settings_not_available">Developer options are not available for this user</string>
- <!-- Error message for users that aren't allowed to modify VPN settings [CHAR LIMIT=none] -->
- <string name="vpn_settings_not_available">VPN settings are not available for this user</string>
- <!-- Error message for users that aren't allowed to modify Tethering settings [CHAR LIMIT=none] -->
- <string name="tethering_settings_not_available">Tethering settings are not available for this user</string>
- <!-- Error message for users that aren't allowed to modify Access Point Names settings [CHAR LIMIT=none] -->
- <string name="apn_settings_not_available">Access Point Name settings are not available for this user</string>
- <string name="enable_adb">USB debugging</string>
- <!-- Setting checkbox summary for Whether to enable USB debugging support on the phone -->
- <string name="enable_adb_summary">Debug mode when USB is connected</string>
- <!-- Setting title to revoke secure USB debugging authorizations -->
- <string name="clear_adb_keys">Revoke USB debugging authorizations</string>
- <!-- [CHAR LIMIT=NONE] Setting checkbox title for Whether to include bug report item in power menu. -->
- <string name="bugreport_in_power">Bug report shortcut</string>
- <!-- [CHAR LIMIT=NONE] Setting checkbox summary for Whether to include bug report item in power -->
- <string name="bugreport_in_power_summary">Show a button in the power menu for taking a bug report</string>
- <!-- Setting Checkbox title whether to keep the screen on when plugged in to a power source -->
- <string name="keep_screen_on">Stay awake</string>
- <!-- setting Checkbox summary whether to keep the screen on when plugged in -->
- <string name="keep_screen_on_summary">Screen will never sleep while charging</string>
- <!-- Setting Checkbox title whether to enable bluetooth HCI snoop log -->
- <string name="bt_hci_snoop_log">Enable Bluetooth HCI snoop log</string>
- <!-- setting Checkbox summary whether to capture all bluetooth HCI packets in a file -->
- <string name="bt_hci_snoop_log_summary">Capture all bluetooth HCI packets in a file</string>
- <!-- setting Checkbox title whether to enable OEM unlock [CHAR_LIMIT=35] -->
- <string name="oem_unlock_enable">OEM unlocking</string>
- <!-- setting Checkbox summary whether to enable OEM unlock [CHAR_LIMIT=50] -->
- <string name="oem_unlock_enable_summary">Allow the bootloader to be unlocked</string>
- <!-- Confirmation dialog title to ensure user wishes to enable OEM unlock and disable theft protection features -->
- <string name="confirm_enable_oem_unlock_title">Allow OEM unlocking?</string>
- <!-- Warning dialog message to confirm user wishes to enable OEM unlock and disable theft protection features -->
- <string name="confirm_enable_oem_unlock_text">WARNING: Device protection features will not work on this device while this setting is turned on.</string>
-
- <!-- UI debug setting: limit size of Android logger buffers -->
- <string name="select_logd_size_title">Logger buffer sizes</string>
- <!-- UI debug setting: limit size of Android logger buffers [CHAR LIMIT=59] -->
- <string name="select_logd_size_dialog_title">Select Logger sizes per log buffer</string>
-
- <!-- UI debug setting: select current app to mock location [CHAR LIMIT=50] -->
- <string name="mock_location_app">Select mock location app</string>
- <!-- UI debug setting: no mock location app has been set [CHAR LIMIT=50] -->
- <string name="mock_location_app_not_set">No mock location app set</string>
- <!-- UI debug setting: mock location app has been set [CHAR LIMIT=50] -->
- <string name="mock_location_app_set">Mock location app: <xliff:g id="app_name">%1$s</xliff:g></string>
-
- <!-- Setting Checkbox title whether to enable view attribute inspection -->
- <string name="debug_view_attributes">Enable view attribute inspection</string>
- <!-- Title of warning dialog about the implications of enabling USB debugging -->
-
- <!-- Preference category for networking debugging development settings. [CHAR LIMIT=50] -->
- <string name="debug_networking_category">Networking</string>
-
- <!-- Setting Checkbox title whether to show options for wireless display certification -->
- <string name="wifi_display_certification">Wireless display certification</string>
- <!-- Setting Checkbox title whether to enable WiFi Verbose Logging. [CHAR LIMIT=40] -->
- <string name="wifi_verbose_logging">Enable Wi\u2011Fi Verbose Logging</string>
- <!-- Setting Checkbox title whether to enable WiFi Aggressive Handover. [CHAR LIMIT=40] -->
- <string name="wifi_aggressive_handover">Aggressive Wi\u2011Fi to Cellular handover</string>
- <!-- Setting Checkbox title whether to enable WiFi Scanning in the presence of traffic. [CHAR LIMIT=80] -->
- <string name="wifi_allow_scan_with_traffic">Always allow Wi\u2011Fi Roam Scans</string>
- <!-- Setting Checkbox title whether to enable WiFi Scanning in the presence of traffic. [CHAR LIMIT=80] -->
- <string name="legacy_dhcp_client">Use legacy DHCP client</string>
- <!-- Setting Checkbox title whether to always keep cellular data active. [CHAR LIMIT=80] -->
- <string name="mobile_data_always_on">Cellular data always active</string>
-
- <!-- setting Checkbox summary whether to show options for wireless display certification -->
- <string name="wifi_display_certification_summary">Show options for wireless display certification</string>
- <!-- Setting Checkbox summary whether to enable Wifi verbose Logging [CHAR LIMIT=80] -->
- <string name="wifi_verbose_logging_summary">Increase Wi\u2011Fi logging level, show per SSID RSSI in Wi\u2011Fi Picker</string>
- <!-- Setting Checkbox summary whether to enable Wifi aggressive handover [CHAR LIMIT=130] -->
- <string name="wifi_aggressive_handover_summary">When enabled, Wi\u2011Fi will be more aggressive in handing over the data connection to Cellular, when Wi\u2011Fi signal is low</string>
- <!-- Setting Checkbox summary whether to always allow WiFi Roam Scans [CHAR LIMIT=130] -->
- <string name="wifi_allow_scan_with_traffic_summary">Allow/Disallow Wi\u2011Fi Roam Scans based on the amount of data traffic present at the interface</string>
- <!-- UI debug setting: limit size of Android logger buffers -->
- <string name="select_logd_size_title">Logger buffer sizes</string>
- <!-- UI debug setting: limit size of Android logger buffers [CHAR LIMIT=59] -->
- <string name="select_logd_size_dialog_title">Select Logger sizes per log buffer</string>
- <!-- UI debug setting: select USB configuration -->
- <string name="select_usb_configuration_title">Select USB Configuration</string>
- <!-- UI debug setting: limit size of Android logger buffers [CHAR LIMIT=59] -->
- <string name="select_usb_configuration_dialog_title">Select USB Configuration</string>
- <!-- Setting Checkbox title whether to allow mock locations -->
- <string name="allow_mock_location">Allow mock locations</string>
- <!-- setting Checkbox summary whether to allow mock locations -->
- <string name="allow_mock_location_summary">Allow mock locations</string>
- <!-- Setting Checkbox title whether to enable view attribute inspection -->
- <string name="debug_view_attributes">Enable view attribute inspection</string>
- <!-- Title of warning dialog about the implications of enabling USB debugging -->
- <!-- Setting Checkbox summary whether to use DHCP client from Lollipop (Android 5.0) [CHAR LIMIT=130] -->
- <string name="legacy_dhcp_client_summary">Use the DHCP client from Lollipop instead of the new Android DHCP client.</string>
- <string name="mobile_data_always_on_summary">Always keep mobile data active, even when Wi\u2011Fi is active (for fast network switching).</string>
- <string name="adb_warning_title">Allow USB debugging?</string>
- <!-- Warning text to user about the implications of enabling USB debugging -->
- <string name="adb_warning_message">USB debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification, and read log data.</string>
- <!-- Message of dialog confirming that user wants to revoke access to adb from all computers they have authorized -->
- <string name="adb_keys_warning_message">Revoke access to USB debugging from all computers you\u2019ve previously authorized?</string>
- <!-- Title of warning dialog about the implications of enabling developer settings -->
- <string name="dev_settings_warning_title">Allow development settings?</string>
- <!-- Warning text to user about the implications of enabling USB debugging -->
- <string name="dev_settings_warning_message">These settings are intended for development use only. They can cause your device and the applications on it to break or misbehave.</string>
- <!-- Title of checkbox setting to perform package verification on apps installed over USB/ADT/ADB [CHAR LIMIT=32] -->
- <string name="verify_apps_over_usb_title">Verify apps over USB</string>
- <!-- Summary of checkbox setting to perform package verification on apps installed over USB/ADT/ADB [CHAR LIMIT=NONE] -->
- <string name="verify_apps_over_usb_summary">Check apps installed via ADB/ADT for harmful behavior.</string>
-
- <!-- Title of checkbox setting that protects external storage. [CHAR LIMIT=32] -->
- <string name="enforce_read_external_title" product="nosdcard">Protect USB storage</string>
- <!-- Summary of checkbox setting that protects external storage. [CHAR LIMIT=64] -->
- <string name="enforce_read_external_summary" product="nosdcard">Apps must request permission to read USB storage</string>
- <!-- Title of dialog confirming that user wants to protect external storage. [CHAR LIMIT=32] -->
- <string name="enforce_read_external_confirm_title" product="nosdcard">Protect USB storage?</string>
- <!-- Message of dialog confirming that user wants to protect external storage. [CHAR LIMIT=NONE] -->
- <string name="enforce_read_external_confirm_message" product="nosdcard">When USB storage is protected, apps must request permission to read data from external storage.\n\nSome apps may not work until updated by their developers.</string>
-
- <!-- Title of checkbox setting that protects external storage. [CHAR LIMIT=32] -->
- <string name="enforce_read_external_title" product="default">Protect SD card</string>
- <!-- Summary of checkbox setting that protects external storage. [CHAR LIMIT=64] -->
- <string name="enforce_read_external_summary" product="default">Apps must request permission to read SD card</string>
- <!-- Title of dialog confirming that user wants to protect external storage. [CHAR LIMIT=32] -->
- <string name="enforce_read_external_confirm_title" product="default">Protect SD card?</string>
- <!-- Message of dialog confirming that user wants to protect external storage. [CHAR LIMIT=NONE] -->
- <string name="enforce_read_external_confirm_message" product="default">When SD card is protected, apps must request permission to read data from external storage.\n\nSome apps may not work until updated by their developers.</string>
-
- <!-- Title of checkbox setting that enables the terminal app. [CHAR LIMIT=32] -->
- <string name="enable_terminal_title">Local terminal</string>
- <!-- Summary of checkbox setting that enables the terminal app. [CHAR LIMIT=64] -->
- <string name="enable_terminal_summary">Enable terminal app that offers local shell access</string>
-
<!-- Title for the screen that lets the user choose a gadget to add to the home screen
(or other screens that can host gadgets). Note to translators: we're still determining
the final name for Gadgets/Widgets, so please translate both for now. -->
@@ -3822,16 +3659,14 @@
<string name="accessibility_power_button_ends_call_prerefence_title">Power button ends call</string>
<!-- Title for the accessibility preference to speak passwords. [CHAR LIMIT=35] -->
<string name="accessibility_toggle_speak_password_preference_title">Speak passwords</string>
+ <!-- Title for the accessibility preference for enabling/disabling large icons for mouse/trackpad pointers. [CHAR LIMIT=35] -->
+ <string name="accessibility_toggle_large_pointer_icon_title">Large mouse pointer</string>
<!-- Title for accessibility preference to choose long-press delay i.e. timeout before it is detected. [CHAR LIMIT=35] -->
<string name="accessibility_long_press_timeout_preference_title">Touch & hold delay</string>
<!-- Title for the accessibility preference to configure display color inversion. [CHAR LIMIT=NONE] -->
<string name="accessibility_display_inversion_preference_title">Color inversion</string>
<!-- Subtitle for the accessibility preference to configure display color inversion. [CHAR LIMIT=NONE] -->
<string name="accessibility_display_inversion_preference_subtitle">(Experimental) May affect performance</string>
- <!-- Title for the accessibility preference to configure display color space correction. [CHAR LIMIT=NONE] -->
- <string name="accessibility_display_daltonizer_preference_title">Color correction</string>
- <!-- Subtitle for the accessibility preference to configure display color space correction. [CHAR LIMIT=NONE] -->
- <string name="accessibility_display_daltonizer_preference_subtitle">This feature is experimental and may affect performance.</string>
<!-- Title for accessibility preference for configuring feature that performs click action soon after mouse/trackpad pointer stops moving. [CHAR LIMIT=NONE] -->
<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] -->
@@ -3841,19 +3676,6 @@
<string name="enable_quick_setting">Show in Quick Settings</string>
<!-- Title for the preference to configure the type of color space correction to apply. [CHAR LIMIT=NONE] -->
<string name="daltonizer_type">Correction mode</string>
- <!-- Summary shown for color space correction preference when its value is overridden by another preference [CHAR LIMIT=35] -->
- <string name="daltonizer_type_overridden">Overridden by <xliff:g id="title" example="Simulate color space">%1$s</xliff:g></string>
-
- <!-- Label for disabling color space adjustment [CHAR LIMIT=45] -->
- <string name="daltonizer_mode_disabled">Disabled</string>
- <!-- Label for converting display colors to grayscale, which simulates monochromacy (complete color blindness). [CHAR LIMIT=45] -->
- <string name="daltonizer_mode_monochromacy">Monochromacy</string>
- <!-- Label for deuteranomaly (red-green color blindness) [CHAR LIMIT=45] -->
- <string name="daltonizer_mode_deuteranomaly">Deuteranomaly (red-green)</string>
- <!-- Label for protanomaly (red-green color blindness) [CHAR LIMIT=45] -->
- <string name="daltonizer_mode_protanomaly">Protanomaly (red-green)</string>
- <!-- Label for tritanomaly (blue-yellow color blindness) [CHAR LIMIT=45] -->
- <string name="daltonizer_mode_tritanomaly">Tritanomaly (blue-yellow)</string>
<!-- Subtitle for the accessibility preference to configure feature that performs click action soon after mouse/trackpad pointer stops moving, in case delay before click is extremely short. Placeholder will be set to the number of milliseconds to which the delay amounts. [CHAR LIMIT=NONE] -->
<plurals name="accessibilty_autoclick_preference_subtitle_extremely_short_delay">
@@ -4593,20 +4415,6 @@
<!-- Default summary text of the "Configure backup account" setting [CHAR LIMIT=80]-->
<string name="backup_configure_account_default_summary">No account is currently storing backed up data</string>
- <!-- Local (desktop) backup password menu title [CHAR LIMIT=25] -->
- <string name="local_backup_password_title">Desktop backup password</string>
- <!-- Summary text of the "local backup password" setting when the user has not supplied a password -->
- <string name="local_backup_password_summary_none">Desktop full backups aren\u2019t currently protected</string>
- <!-- Summary text of the "local backup password" setting when the user has already supplied a password -->
- <string name="local_backup_password_summary_change">Touch to change or remove the password for desktop full backups</string>
-
- <!-- Toast message shown when the user successfully sets a new local backup password [CHAR LIMIT=80] -->
- <string name="local_backup_password_toast_success">New backup password set</string>
- <!-- Toast message shown when setting a new local backup password fails due to the user not correctly typing the password again for confirmation [CHAR LIMIT=80] -->
- <string name="local_backup_password_toast_confirmation_mismatch">New password and confirmation don\u2019t match</string>
- <!-- Toast message shown when setting a new local backup password fails due to the user not supplying the correct existing password. The phrasing here is deliberately quite general. [CHAR LIMIT=80] -->
- <string name="local_backup_password_toast_validation_failure">Failure setting backup password</string>
-
<!-- Dialog title for confirmation to erase backup data from server -->
<string name="backup_erase_dialog_title"></string>
<!-- Dialog title for confirmation to erase backup data from server -->
@@ -4905,168 +4713,6 @@
<!-- action to select all [CHAR LIMIT=30] -->
<string name="select_all">Select all</string>
- <!-- HDCP checking title, used for debug purposes only. [CHAR LIMIT=25] -->
- <string name="hdcp_checking_title">HDCP checking</string>
- <!-- HDCP checking dialog title, used for debug purposes only. [CHAR LIMIT=25] -->
- <string name="hdcp_checking_dialog_title">Set HDCP checking behavior</string>
-
- <!-- Preference category for app debugging development settings. [CHAR LIMIT=50] -->
- <string name="debug_debugging_category">Debugging</string>
-
- <!-- UI debug setting: select current app to debug [CHAR LIMIT=50] -->
- <string name="debug_app">Select debug app</string>
- <!-- UI debug setting: no debug app has been set [CHAR LIMIT=50] -->
- <string name="debug_app_not_set">No debug application set</string>
- <!-- UI debug setting: debug app has been set [CHAR LIMIT=50] -->
- <string name="debug_app_set">Debugging application: <xliff:g id="app_name">%1$s</xliff:g></string>
-
- <!-- UI debug setting: title for app picker dialog [CHAR LIMIT=50] -->
- <string name="select_application">Select application</string>
- <!-- UI debug setting: label for app picker to select no applicatiojn [CHAR LIMIT=50] -->
- <string name="no_application">Nothing</string>
-
- <!-- UI debug setting: wait for debugger to attach to debugging process? [CHAR LIMIT=50] -->
- <string name="wait_for_debugger">Wait for debugger</string>
- <!-- UI debug setting: wait for debugger to attach to debugging process summary [CHAR LIMIT=500] -->
- <string name="wait_for_debugger_summary">Debugged application waits for debugger to
- attach before executing</string>
-
- <!-- Preference category for input debugging development settings. [CHAR LIMIT=25] -->
- <string name="debug_input_category">Input</string>
-
- <!-- Preference category for drawing debugging development settings. [CHAR LIMIT=25] -->
- <string name="debug_drawing_category">Drawing</string>
-
- <!-- Preference category for hardware accelerated drawing debugging development settings. [CHAR LIMIT=50] -->
- <string name="debug_hw_drawing_category">Hardware accelerated rendering</string>
-
- <!-- Preference category for media development settings. [CHAR LIMIT=50] -->
- <string name="media_category">Media</string>
-
- <!-- Preference category for monitoring debugging development settings. [CHAR LIMIT=25] -->
- <string name="debug_monitoring_category">Monitoring</string>
-
- <!-- UI debug setting: always enable strict mode? [CHAR LIMIT=25] -->
- <string name="strict_mode">Strict mode enabled</string>
- <!-- UI debug setting: show strict mode summary [CHAR LIMIT=50] -->
- <string name="strict_mode_summary">Flash screen when apps do long operations
- on main thread</string>
-
- <!-- UI debug setting: show pointer location? [CHAR LIMIT=25] -->
- <string name="pointer_location">Pointer location</string>
- <!-- UI debug setting: show pointer location summary [CHAR LIMIT=50] -->
- <string name="pointer_location_summary">Screen overlay showing current touch data</string>
-
- <!-- UI debug setting: show touches? [CHAR LIMIT=25] -->
- <string name="show_touches">Show touches</string>
- <!-- UI debug setting: show touches location summary [CHAR LIMIT=50] -->
- <string name="show_touches_summary">Show visual feedback for touches</string>
-
- <!-- UI debug setting: show where surface updates happen? [CHAR LIMIT=25] -->
- <string name="show_screen_updates">Show surface updates</string>
- <!-- UI debug setting: show surface updates summary [CHAR LIMIT=50] -->
- <string name="show_screen_updates_summary">Flash entire window surfaces when they update</string>
-
- <!-- UI debug setting: show where window updates happen with GPU rendering? [CHAR LIMIT=25] -->
- <string name="show_hw_screen_updates">Show GPU view updates</string>
- <!-- UI debug setting: show GPU rendering screen updates summary [CHAR LIMIT=50] -->
- <string name="show_hw_screen_updates_summary">Flash views inside windows when drawn with the GPU</string>
-
- <!-- UI debug setting: show when hardware layers get updated [CHAR LIMIT=25] -->
- <string name="show_hw_layers_updates">Show hardware layers updates</string>
- <!-- UI debug setting: show hardware layers updates summary [CHAR LIMIT=50] -->
- <string name="show_hw_layers_updates_summary">Flash hardware layers green when they update</string>
-
- <!-- UI debug setting: show the amount of overdraw in apps using the GPU [CHAR LIMIT=25] -->
- <string name="debug_hw_overdraw">Debug GPU overdraw</string>
-
- <!-- UI debug setting: disable use of overlays? [CHAR LIMIT=25] -->
- <string name="disable_overlays">Disable HW overlays</string>
- <!-- UI debug setting: disable use of overlays summary [CHAR LIMIT=50] -->
- <string name="disable_overlays_summary">Always use GPU for screen compositing</string>
-
- <!-- UI debug setting: simulate color space anomalies. [CHAR LIMIT=25] -->
- <string name="simulate_color_space">Simulate color space</string>
-
- <!-- UI debug setting: enable various types of OpenGL traces [CHAR LIMIT=25] -->
- <string name="enable_opengl_traces_title">Enable OpenGL traces</string>
-
- <!-- UI debug setting: disable USB audio routing title [CHAR LIMIT=32] -->
- <string name="usb_audio_disable_routing">Disable USB audio routing</string>
- <!-- UI debug setting: disable USB audio routing summary [CHAR LIMIT=50] -->
- <string name="usb_audio_disable_routing_summary">Disable automatic routing to USB audio peripherals</string>
-
- <!-- UI debug setting: show layout bounds information [CHAR LIMIT=25] -->
- <string name="debug_layout">Show layout bounds</string>
- <!-- UI debug setting: show layout bounds information summary [CHAR LIMIT=50] -->
- <string name="debug_layout_summary">Show clip bounds, margins, etc.</string>
-
- <!-- UI debug setting: force right to left layout [CHAR LIMIT=37] -->
- <string name="force_rtl_layout_all_locales">Force RTL layout direction</string>
- <!-- UI debug setting: force right to left layout summary [CHAR LIMIT=100] -->
- <string name="force_rtl_layout_all_locales_summary">Force screen layout direction to RTL for all locales</string>
-
- <!-- UI debug setting: show how CPU is being used? [CHAR LIMIT=25] -->
- <string name="show_cpu_usage">Show CPU usage</string>
- <!-- UI debug setting: show cpu usage summary [CHAR LIMIT=50] -->
- <string name="show_cpu_usage_summary">Screen overlay showing current CPU usage</string>
-
- <!-- UI debug setting: force hardware acceleration to render apps [CHAR LIMIT=25] -->
- <string name="force_hw_ui">Force GPU rendering</string>
- <!-- UI debug setting: force hardware acceleration summary [CHAR LIMIT=50] -->
- <string name="force_hw_ui_summary">Force use of GPU for 2d drawing</string>
-
- <!-- UI debug setting: force anti-aliasing to render apps [CHAR LIMIT=25] -->
- <string name="force_msaa">Force 4x MSAA</string>
- <!-- UI debug setting: force anti-aliasing summary [CHAR LIMIT=50] -->
- <string name="force_msaa_summary">Enable 4x MSAA in OpenGL ES 2.0 apps</string>
-
- <!-- UI debug setting: show when non-rectangular clip operations are used [CHAR LIMIT=100] -->
- <string name="show_non_rect_clip">Debug non-rectangular clip operations</string>
-
- <!-- UI debug setting: profile time taken by hardware acceleration to render apps [CHAR LIMIT=25] -->
- <string name="track_frame_time">Profile GPU rendering</string>
-
- <!-- UI debug setting: scaling factor for window animations [CHAR LIMIT=25] -->
- <string name="window_animation_scale_title">Window animation scale</string>
-
- <!-- UI debug setting: scaling factor for transition animations [CHAR LIMIT=25] -->
- <string name="transition_animation_scale_title">Transition animation scale</string>
-
- <!-- UI debug setting: scaling factor for all Animator-based animations [CHAR LIMIT=25] -->
- <string name="animator_duration_scale_title">Animator duration scale</string>
-
- <!-- UI debug setting: simulate secondary display devices using overlays [CHAR LIMIT=25] -->
- <string name="overlay_display_devices_title">Simulate secondary displays</string>
-
- <!-- Preference category for application debugging development settings. [CHAR LIMIT=25] -->
- <string name="debug_applications_category">Apps</string>
-
- <!-- UI debug setting: immediately destroy activities? [CHAR LIMIT=25] -->
- <string name="immediately_destroy_activities">Don\u2019t keep activities</string>
- <!-- UI debug setting: immediately destroy activities summary [CHAR LIMIT=50] -->
- <string name="immediately_destroy_activities_summary">Destroy every activity as soon as
- the user leaves it</string>
-
- <!-- UI debug setting: limit number of running background processes [CHAR LIMIT=25] -->
- <string name="app_process_limit_title">Background process limit</string>
-
- <!-- UI debug setting: show all ANRs? [CHAR LIMIT=25] -->
- <string name="show_all_anrs">Show all ANRs</string>
- <!-- UI debug setting: show all ANRs summary [CHAR LIMIT=50] -->
- <string name="show_all_anrs_summary">Show App Not Responding dialog
- for background apps</string>
-
- <!-- UI debug setting: force allow apps on external storage [CHAR LIMIT=50] -->
- <string name="force_allow_on_external">Force allow apps on external</string>
- <!-- UI debug setting: force allow on external summary [CHAR LIMIT=150] -->
- <string name="force_allow_on_external_summary">Makes any app elligible to be written to external storage, regardless of manifest values</string>
-
- <!-- UI debug setting: force all activites to be resizable for multiwindow [CHAR LIMIT=50] -->
- <string name="force_resizable_activities">Force activities to be resizable</string>
- <!-- UI debug setting: force allow on external summary [CHAR LIMIT=150] -->
- <string name="force_resizable_activities_summary">Makes all activities resizable for multi-window, regardless of manifest values.</string>
-
<!-- Activity title for network data usage summary. [CHAR LIMIT=25] -->
<string name="data_usage_summary_title">Data usage</string>
<!-- Activity title for Appk data usage summary. [CHAR LIMIT=25] -->
@@ -5866,46 +5512,44 @@
<string name="search_results_label">Results</string>
<!--Search Keywords [CHAR LIMIT=NONE]-->
- <string name="keywords_wifi">wifi wi-fi network connection</string>
- <string name="keywords_more_default_sms_app">text message texting messages messaging</string>
- <string name="keywords_more_mobile_networks">cellular cell carrier wireless data 4g 3g 2g lte</string>
- <string name="keywords_wifi_calling">wifi wi-fi call calling</string>
+ <string name="keywords_wifi">wifi, wi-fi, network connection</string>
+ <string name="keywords_more_default_sms_app">text message, texting, messages, messaging</string>
+ <string name="keywords_more_mobile_networks">cellular, cell carrier, wireless, data, 4g, 3g, 2g, lte</string>
+ <string name="keywords_wifi_calling">wifi, wi-fi, call, calling</string>
<string name="keywords_home">launcher</string>
- <string name="keywords_display">screen touchscreen</string>
- <string name="keywords_display_brightness_level">dim screen touchscreen battery</string>
- <string name="keywords_display_auto_brightness">dim screen touchscreen battery</string>
- <!-- Search keywords for display light/dark theme: dark theme, night mode, dim screen, invert brightness [CHAR LIMIT=NONE] -->
- <string name="keywords_display_night_mode">dark theme night mode dim screen invert brightness</string>
- <string name="keywords_display_wallpaper">background personalize customize display</string>
+ <string name="keywords_display">screen, touchscreen</string>
+ <string name="keywords_display_brightness_level">dim screen, touchscreen, battery</string>
+ <string name="keywords_display_auto_brightness">dim screen, touchscreen, battery</string>
+ <string name="keywords_display_night_mode">dark theme, night mode, dim screen, invert brightness</string>
+ <string name="keywords_display_wallpaper">background, personalize, customize display</string>
<string name="keywords_display_font_size">text size</string>
- <string name="keywords_display_cast_screen">project cast</string>
- <string name="keywords_storage">space disk hard drive device usage</string>
- <string name="keywords_battery">power usage charge</string>
- <string name="keywords_spell_checker">spelling dictionary spellcheck auto-correct</string>
- <string name="keywords_voice_input">recognizer input speech speak language hands-free hand free recognition offensive word audio history bluetooth headset</string>
- <string name="keywords_text_to_speech_output">rate language default speak speaking tts accessibility reader blind</string>
- <string name="keywords_date_and_time">clock military</string>
- <string name="keywords_network_reset">reset restore factory</string>
- <string name="keywords_factory_data_reset">wipe delete restore clear remove</string>
+ <string name="keywords_display_cast_screen">project, cast</string>
+ <string name="keywords_storage">space, disk, hard drive, device usage</string>
+ <string name="keywords_battery">power usage, charge</string>
+ <string name="keywords_spell_checker">spelling, dictionary, spellcheck, auto-correct</string>
+ <string name="keywords_voice_input">recognizer, input, speech, speak, language, hands-free, hand free, recognition, offensive, word, audio, history, bluetooth headset</string>
+ <string name="keywords_text_to_speech_output">rate, language, default, speak, speaking, tts, accessibility, screen reader, blind</string>
+ <string name="keywords_date_and_time">clock, military</string>
+ <string name="keywords_network_reset">reset, restore, factory</string>
+ <string name="keywords_factory_data_reset">wipe, delete, restore, clear, remove</string>
<string name="keywords_printing">printer</string>
<string name="keywords_sounds">speaker beep</string>
- <string name="keywords_sounds_and_notifications_interruptions">dont don\u2019t disturb interrupt interruption break</string>
+ <string name="keywords_sounds_and_notifications_interruptions">dont don\u2019t disturb, interrupt, interruption, break</string>
<string name="keywords_app">RAM</string>
- <string name="keywords_location">nearby location history reporting</string>
+ <string name="keywords_location">nearby, location, history, reporting</string>
<string name="keywords_location_mode">accuracy</string>
<string name="keywords_accounts">account</string>
- <string name="keywords_users">restriction restrict restricted</string>
- <string name="keywords_keyboard_and_ime">text correction correct sound vibrate auto language gesture suggest suggestion theme offensive word type emoji international</string>
- <string name="keywords_reset_apps">reset preferences default</string>
- <string name="keywords_emergency_app">emergency ice app default</string>
- <string name="keywords_default_phone_app">phone dialer default</string>
- <string name="keywords_all_apps">apps download applications system</string>
- <string name="keywords_app_permissions">apps permissions security</string>
- <string name="keywords_default_apps">apps default</string>
- <string name="keywords_ignore_optimizations">ignore optimizations doze app standby</string>
- <string name="keywords_color_mode">vibrant rgb srgb color natural standard</string>
- <!-- Search keywords for different screen unlock modes : slide to unlock, password, pattern and PIN [CHAR LIMIT=none] -->
- <string name="keywords_lockscreen">slide password pattern pin</string>
+ <string name="keywords_users">restriction, restrict, restricted</string>
+ <string name="keywords_keyboard_and_ime">text correction, correct, sound, vibrate, auto, language, gesture, suggest, suggestion, theme, offensive, word, type, emoji, international</string>
+ <string name="keywords_reset_apps">reset, preferences, default</string>
+ <string name="keywords_emergency_app">emergency, ice, app, default</string>
+ <string name="keywords_default_phone_app">phone, dialer, default</string>
+ <string name="keywords_all_apps">apps, download, applications, system</string>
+ <string name="keywords_app_permissions">apps, permissions, security</string>
+ <string name="keywords_default_apps">apps, default</string>
+ <string name="keywords_ignore_optimizations">ignore optimizations, doze, app standby</string>
+ <string name="keywords_color_mode">vibrant, RGB, sRGB, color, natural, standard</string>
+ <string name="keywords_lockscreen">slide to unlock, password, pattern, PIN</string>
<!-- NFC Wi-Fi pairing/setup strings-->
@@ -6055,7 +5699,26 @@
<!-- Sound & notification > Notification section: Title for the option managing notifications per topic. [CHAR LIMIT=30] -->
<string name="topic_notifications_title">Topic notifications</string>
+ <!-- [CHAR LIMIT=100] Notification topic list header -->
+ <string name="notification_topic_categories">Categories</string>
+ <!-- [CHAR LIMIT=100] Notification importance slider title -->
+ <string name="notification_importance_title">Importance</string>
+
+ <!-- [CHAR LIMIT=100] Notification Importance slider: blocked importance level description -->
+ <string name="notification_importance_blocked">Blocked: Never show these notifications</string>
+
+ <!-- [CHAR LIMIT=100] Notification Importance slider: low importance level description -->
+ <string name="notification_importance_low">Low: Silently show at the bottom of the notification list</string>
+
+ <!-- [CHAR LIMIT=100] Notification Importance slider: normal importance level description -->
+ <string name="notification_importance_default">Normal: Silently show these notifications</string>
+
+ <!-- [CHAR LIMIT=100] Notification Importance slider: high importance level description -->
+ <string name="notification_importance_high">High: Show at the top of the notifications list and make sound</string>
+
+ <!-- [CHAR LIMIT=100] Notification Importance slider: max importance level description -->
+ <string name="notification_importance_max">Urgent: Peek onto the screen and make sound</string>
<!-- Sound & notification > Advanced section: Title for managing notification listeners option. [CHAR LIMIT=30] -->
<string name="manage_notification_access_title">Notification access</string>
@@ -6124,6 +5787,9 @@
<!-- [CHAR LIMIT=20] Notification settings: App notifications dialog dismiss button caption -->
<string name="app_notifications_dialog_done">Done</string>
+ <!-- [CHAR LIMIT=150] App notification settings: App notifications Importance title -->
+ <string name="app_notification_importance_title">Importance</string>
+
<!-- [CHAR LIMIT=40] Zen mode settings: Rule name option and edit dialog title -->
<string name="zen_mode_rule_name">Rule name</string>
@@ -6778,12 +6444,11 @@
usb_use_file_transfer, use_use_photo_transfer, and usb_use_MIDI -->
<string name="usb_use">Use USB for</string>
- <!-- Settings item title for inactive apps [CHAR LIMIT=35] -->
- <string name="inactive_apps_title">Inactive apps</string>
- <!-- Settings item summary for inactive app [CHAR LIMIT=100] -->
- <string name="inactive_app_inactive_summary">Inactive. Touch to toggle.</string>
- <!-- Settings item summary for active app [CHAR LIMIT=100] -->
- <string name="inactive_app_active_summary">Active. Touch to toggle.</string>
+ <!-- Settings item title for background check prefs [CHAR LIMIT=35] -->
+ <string name="background_check_pref">Background check</string>
+
+ <!-- Settings screen title for background check prefs [CHAR LIMIT=35] -->
+ <string name="background_check_title">Full background access</string>
<!-- Title for the "context" preference to determine whether assist can access the data currently displayed on-screen [CHAR LIMIT=40] -->
<string name="assist_access_context_title">Use text from screen</string>
@@ -6864,6 +6529,12 @@
<!-- Zen mode access settings - summary for warning dialog when enabling access [CHAR LIMIT=NONE] -->
<string name="zen_access_warning_dialog_summary">The app will be able to turn on/off Do Not Disturb and make changes to related settings.</string>
+ <!-- Zen mode access settings - title for warning dialog when revoking access [CHAR LIMIT=NONE] -->
+ <string name="zen_access_revoke_warning_dialog_title">Revoke access to Do Not Disturb for <xliff:g id="app" example="Tasker">%1$s</xliff:g>?</string>
+
+ <!-- Zen mode access settings - summary for warning dialog when revoking access [CHAR LIMIT=NONE] -->
+ <string name="zen_access_revoke_warning_dialog_summary">All Do Not Disturb rules created by this app will be removed.</string>
+
<!-- Ignore battery optimizations on label [CHAR LIMIT=30] -->
<string name="ignore_optimizations_on">Don\u2019t optimize</string>
@@ -6959,43 +6630,33 @@
<!-- Description of setting that controls gesture to open camera by double tapping the power button [CHAR LIMIT=NONE] -->
<string name="camera_double_tap_power_gesture_desc">Quickly open camera without unlocking your screen</string>
- <!-- Name of each color mode for the display. [CHAR LIMIT=40] -->
- <string-array name="color_mode_names">
- <item>Vibrant (default)</item>
- <item>Natural</item>
- <item>Standard</item>
- </string-array>
+ <!-- Title of setting that controls screen zoom (e.g. how large interface elements appear). [CHAR LIMIT=40] -->
+ <string name="screen_zoom_title">Screen zoom</string>
+ <!-- Keywords for setting that controls screen zoom (e.g. how large interface elements appear). [CHAR LIMIT=NONE] -->
+ <string name="screen_zoom_keywords">display density, screen zoom, scale, scaling</string>
- <!-- Description of each color mode for the display. [CHAR LIMIT=NONE] -->
- <string-array name="color_mode_descriptions">
- <item>Enhanced colors</item>
- <item>Natural colors as seen by the eye</item>
- <item>Colors optimized for digital content</item>
- </string-array>
+ <string name="screen_zoom_summary">Choose how zoomed you want the screen using the slider below the preview image.</string>
- <!-- Name of feature to change color setting for the display [CHAR LIMIT=60] -->
- <string name="picture_color_mode">Picture color mode</string>
+ <!-- Title of the screen zoom preview activity. -->
+ <string name="screen_zoom_preview_title">Preview</string>
+ <!-- Description for the button that makes interface elements smaller. [CHAR_LIMIT=NONE] -->
+ <string name="screen_zoom_make_smaller_desc">Make smaller</string>
+ <!-- Description for the button that makes interface elements larger. [CHAR_LIMIT=NONE] -->
+ <string name="screen_zoom_make_larger_desc">Make larger</string>
- <!-- Description of feature to change color setting for the display [CHAR LIMIT=NONE] -->
- <string name="picture_color_mode_desc">Use sRGB</string>
-
- <!-- Title of setting that controls display scale (e.g. density). [CHAR LIMIT=40] -->
- <string name="force_density_preference_title">Display scale</string>
- <!-- Keywords for setting that controls display scale (e.g. density). [CHAR LIMIT=NONE] -->
- <string name="force_density_keywords">display density zoom scale scaling</string>
- <!-- Description for the display scale that makes interface elements small. [CHAR LIMIT=24] -->
- <string name="force_density_summary_small">Small</string>
- <!-- Description for the device's default display scale. [CHAR LIMIT=24] -->
- <string name="force_density_summary_normal">Normal</string>
- <!-- Description for the display scale that makes interface elements large. [CHAR LIMIT=24] -->
- <string name="force_density_summary_large">Large</string>
- <!-- Description for the display scale that makes interface elements larger. [CHAR LIMIT=24] -->
- <string name="force_density_summary_very_large">Larger</string>
- <!-- Description for the display scale that makes interface elements largest. [CHAR LIMIT=24] -->
- <string name="force_density_summary_extremely_large">Largest</string>
- <!-- Description for a custom display scale. This shows the requested display
- density in raw pixels per inch rather than computing a scale amount. [CHAR LIMIT=24] -->
- <string name="force_density_summary_custom">Custom (<xliff:g id="densityDpi" example="160">%d</xliff:g>)</string>
+ <!-- Description for the screen zoom level that makes interface elements small. [CHAR LIMIT=24] -->
+ <string name="screen_zoom_summary_small">Small</string>
+ <!-- Description for the device's default screen zoom level. [CHAR LIMIT=24] -->
+ <string name="screen_zoom_summary_normal">Normal</string>
+ <!-- Description for the screen zoom level that makes interface elements large. [CHAR LIMIT=24] -->
+ <string name="screen_zoom_summary_large">Large</string>
+ <!-- Description for the screen zoom level that makes interface elements larger. [CHAR LIMIT=24] -->
+ <string name="screen_zoom_summary_very_large">Larger</string>
+ <!-- Description for the screen zoom level that makes interface elements largest. [CHAR LIMIT=24] -->
+ <string name="screen_zoom_summary_extremely_large">Largest</string>
+ <!-- Description for a custom screen zoom level. This shows the requested display
+ density in raw pixels per inch rather than using a relative description. [CHAR LIMIT=24] -->
+ <string name="screen_zoom_summary_custom">Custom (<xliff:g id="densityDpi" example="160">%d</xliff:g>)</string>
<!-- Button to show all top-level settings items [CHAR LIMIT=20] -->
<string name="see_all">See all</string>
@@ -7040,4 +6701,51 @@
<!-- Summary of device info page [CHAR LIMIT=NONE] -->
<string name="about_summary">Android <xliff:g id="version" example="6.0">%1$s</xliff:g></string>
+
+ <!-- TODO: Update these strings with the finalized ones. -->
+ <string name="disabled_by_policy_title">Disabled by policy</string>
+ <string name="disabled_by_admin_msg">Disabled by your <xliff:g id="organisation_name" example="organisation">%s</xliff:g>\'s administrator.</string>
+ <string name="default_organisation_name">organisation</string>
+ <string name="default_admin_support_msg">Contact them to learn more.</string>
+ <string name="list_of_administrators">List of administrators</string>
+
+ <!-- Turn off a conditional state of the device (e.g. airplane mode, or hotspot) [CHAR LIMIT=30] -->
+ <string name="condition_turn_off">Turn off</string>
+
+ <!-- Turn on a conditional state of the device (e.g. cellular data) [CHAR LIMIT=30] -->
+ <string name="condition_turn_on">Turn on</string>
+
+ <!-- Title of condition that hotspot is on [CHAR LIMIT=30] -->
+ <string name="condition_hotspot_title">Hotspot is on</string>
+
+ <!-- Summary of condition that hotspot is on [CHAR LIMIT=NONE] -->
+ <string name="condition_hotspot_summary">Portable Wi-Fi hotspot <xliff:g name="ap_name" example="AndroidAP">%1$s</xliff:g> is active, Wi-Fi for this device is turned off.</string>
+
+ <!-- Title of condition that airplane mode is on [CHAR LIMIT=30] -->
+ <string name="condition_airplane_title">Airplane mode is on</string>
+
+ <!-- Summary of condition that airplane mode is on [CHAR LIMIT=NONE] -->
+ <string name="condition_airplane_summary">Wi-Fi, Bluetooth, and cellular network are turned off. You can\'t make phone calls or connect to the Internet.</string>
+
+ <!-- Title of condition that do not disturb is on [CHAR LIMIT=30] -->
+ <string name="condition_zen_title">Do not disturb is on (<xliff:g name="zen_mode_type" example="Alarms only">%1$s</xliff:g>)</string>
+
+ <!-- Title of condition that battery saver is on [CHAR LIMIT=30] -->
+ <string name="condition_battery_title">Battery Saver is on</string>
+
+ <!-- Summary of condition that battery saver is on [CHAR LIMIT=NONE] -->
+ <string name="condition_battery_summary">Performance is reduced. Location services and background data are turned off.</string>
+
+ <!-- Title of condition that cellular data is off [CHAR LIMIT=30] -->
+ <string name="condition_cellular_title">Cellular data is off</string>
+
+ <!-- Summary of condition that cellular data is off [CHAR LIMIT=NONE] -->
+ <string name="condition_cellular_summary">Internet is available only via Wi-Fi</string>
+
+ <!-- Title of condition that background data is off [CHAR LIMIT=30] -->
+ <string name="condition_bg_data_title">Background data is off</string>
+
+ <!-- Summary of condition that background data is off [CHAR LIMIT=NONE] -->
+ <string name="condition_bg_data_summary">Background data is only available via Wi-Fi. This may affect some apps or services when Wi-Fi is not available.</string>
+
</resources>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index e72ad30..b15a77c 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -101,6 +101,7 @@
<style name="PreferenceTheme" parent="@android:style/Theme.DeviceDefault.Settings">
<item name="@android:preferenceStyle">@style/Preference</item>
+ <item name="@dropdownPreferenceStyle">@style/Preference.DropDown.Material</item>
<item name="@android:preferenceFragmentStyle">@style/PreferenceFragmentStyle</item>
<item name="apnPreferenceStyle">@style/ApnPreference</item>
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index 881037d..791f1b8 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -68,6 +68,10 @@
android:title="@string/accessibility_toggle_speak_password_preference_title"
android:persistent="false"/>
+ <SwitchPreference
+ android:key="toggle_large_pointer_icon"
+ android:title="@string/accessibility_toggle_large_pointer_icon_title" />
+
<PreferenceScreen
android:fragment="com.android.settings.accessibility.ToggleGlobalGesturePreferenceFragment"
android:key="enable_global_gesture_preference_screen"
diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml
index 6e27a07..5f00caf 100644
--- a/res/xml/app_notification_settings.xml
+++ b/res/xml/app_notification_settings.xml
@@ -30,7 +30,12 @@
<Preference
android:key="app_settings"
android:title="@string/app_notification_preferences"
- android:order="5"
+ android:order="2"
android:persistent="false" />
+ <PreferenceCategory
+ android:key="categories"
+ android:title="@string/notification_topic_categories"
+ android:order="3" />
+
</PreferenceScreen>
diff --git a/res/xml/battery_saver_settings.xml b/res/xml/battery_saver_settings.xml
index 0134c6f..cc6d9af 100644
--- a/res/xml/battery_saver_settings.xml
+++ b/res/xml/battery_saver_settings.xml
@@ -19,9 +19,10 @@
android:key="battery_saver">
<!-- Turn on automatically -->
- <com.android.settings.DropDownPreference
+ <DropDownPreference
android:key="turn_on_automatically"
android:title="@string/battery_saver_turn_on_automatically_title"
+ android:summary="%s"
android:persistent="false" />
<!-- Feature description text -->
diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml
index aa15f06..d64132a 100644
--- a/res/xml/configure_notification_settings.xml
+++ b/res/xml/configure_notification_settings.xml
@@ -26,9 +26,10 @@
android:persistent="false" />
<!-- When device is locked -->
- <com.android.settings.DropDownPreference
+ <DropDownPreference
android:key="lock_screen_notifications"
android:title="@string/lock_screen_notifications_title"
+ android:summary="%s"
android:persistent="false" />
<PreferenceCategory
diff --git a/res/xml/dashboard_categories.xml b/res/xml/dashboard_categories.xml
deleted file mode 100644
index d437dcf..0000000
--- a/res/xml/dashboard_categories.xml
+++ /dev/null
@@ -1,261 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<dashboard-categories
- xmlns:android="http://schemas.android.com/apk/res/android">
-
- <!-- WIRELESS and NETWORKS -->
- <dashboard-category
- android:id="@+id/wireless_section"
- android:key="@string/category_key_wireless"
- android:title="@string/header_category_wireless_networks" >
-
- <!-- Wifi -->
- <dashboard-tile
- android:id="@+id/wifi_settings"
- android:title="@string/wifi_settings_title"
- android:fragment="com.android.settings.wifi.WifiSettings"
- android:icon="@drawable/ic_settings_wireless"
- />
-
- <!-- Bluetooth -->
- <dashboard-tile
- android:id="@+id/bluetooth_settings"
- android:title="@string/bluetooth_settings_title"
- android:fragment="com.android.settings.bluetooth.BluetoothSettings"
- android:icon="@drawable/ic_settings_bluetooth"
- />
-
- <!-- SIM Cards -->
- <dashboard-tile
- android:id="@+id/sim_settings"
- android:title="@string/sim_settings_title"
- android:fragment="com.android.settings.sim.SimSettings"
- android:icon="@drawable/ic_settings_sim"
- />
-
- <!-- Data Usage -->
- <dashboard-tile
- android:id="@+id/data_usage_settings"
- android:title="@string/data_usage_summary_title"
- android:fragment="com.android.settings.DataUsageSummary"
- android:icon="@drawable/ic_settings_data_usage"
- />
-
- <!-- Operator hook -->
- <dashboard-tile
- android:id="@+id/operator_settings"
- android:fragment="com.android.settings.WirelessSettings" >
- <intent android:action="com.android.settings.OPERATOR_APPLICATION_SETTING" />
- </dashboard-tile>
-
- <!-- Other wireless and network controls -->
- <dashboard-tile
- android:id="@+id/wireless_settings"
- android:title="@string/radio_controls_title"
- android:fragment="com.android.settings.WirelessSettings"
- android:icon="@drawable/ic_settings_more"
- />
-
- </dashboard-category>
-
- <!-- DEVICE -->
- <dashboard-category
- android:id="@+id/device_section"
- android:key="@string/category_key_device"
- android:title="@string/header_category_device" >
-
- <!-- Home -->
- <dashboard-tile
- android:id="@+id/home_settings"
- android:title="@string/home_settings"
- android:fragment="com.android.settings.HomeSettings"
- android:icon="@drawable/ic_settings_home"
- />
-
- <!-- Display -->
- <dashboard-tile
- android:id="@+id/display_settings"
- android:title="@string/display_settings"
- android:fragment="com.android.settings.DisplaySettings"
- android:icon="@drawable/ic_settings_display"
- />
-
- <!-- Notifications -->
- <dashboard-tile
- android:id="@+id/notification_settings"
- android:title="@string/notification_settings"
- android:fragment="com.android.settings.notification.NotificationSettings"
- android:icon="@drawable/ic_settings_notifications"
- />
-
- <!-- Application Settings -->
- <dashboard-tile
- android:id="@+id/application_settings"
- android:title="@string/applications_settings"
- android:fragment="com.android.settings.applications.ManageApplications"
- android:icon="@drawable/ic_settings_applications"
- />
-
- <!-- Storage -->
- <dashboard-tile
- android:id="@+id/storage_settings"
- android:title="@string/storage_usb_settings"
- android:fragment="com.android.settings.deviceinfo.StorageSettings"
- android:icon="@drawable/ic_settings_storage"
- />
-
- <!-- Battery -->
- <dashboard-tile
- android:id="@+id/battery_settings"
- android:title="@string/power_usage_summary_title"
- android:fragment="com.android.settings.fuelgauge.PowerUsageSummary"
- android:icon="@drawable/ic_settings_battery"
- />
-
- <!-- Memory -->
- <dashboard-tile
- android:id="@+id/manage_memory"
- android:title="@string/memory_settings_title"
- android:fragment="com.android.settings.applications.ProcessStatsSummary"
- android:icon="@drawable/ic_settings_memory"
- />
-
- <!-- Manage users -->
- <dashboard-tile
- android:id="@+id/user_settings"
- android:title="@string/user_settings_title"
- android:fragment="com.android.settings.users.UserSettings"
- android:icon="@drawable/ic_settings_multiuser"
- />
-
- <!-- Manage NFC payment apps -->
- <dashboard-tile
- android:id="@+id/nfc_payment_settings"
- android:title="@string/nfc_payment_settings_title"
- android:fragment="com.android.settings.nfc.PaymentSettings"
- android:icon="@drawable/ic_settings_nfc_payment"
- />
-
- <!-- Manufacturer hook -->
- <dashboard-tile
- android:id="@+id/manufacturer_settings"
- android:fragment="com.android.settings.WirelessSettings">
- <intent android:action="com.android.settings.MANUFACTURER_APPLICATION_SETTING" />
- </dashboard-tile>
-
- </dashboard-category>
-
- <!-- PERSONAL -->
- <dashboard-category
- android:id="@+id/personal_section"
- android:key="@string/category_key_personal"
- android:title="@string/header_category_personal" >
-
- <!-- Location -->
- <dashboard-tile
- android:id="@+id/location_settings"
- android:title="@string/location_settings_title"
- android:fragment="com.android.settings.location.LocationSettings"
- android:icon="@drawable/ic_settings_location"
- />
-
- <!-- Security -->
- <dashboard-tile
- android:id="@+id/security_settings"
- android:title="@string/security_settings_title"
- android:fragment="com.android.settings.SecuritySettings"
- android:icon="@drawable/ic_settings_security"
- />
-
- <!-- Account -->
- <dashboard-tile
- android:id="@+id/account_settings"
- android:title="@string/account_settings_title"
- android:fragment="com.android.settings.accounts.AccountSettings"
- android:icon="@drawable/ic_settings_accounts"
- />
-
- <!-- Marker for where to place external tiles in this category -->
- <external-tiles />
-
- <!-- Language -->
- <dashboard-tile
- android:id="@+id/language_settings"
- android:title="@string/language_settings"
- android:fragment="com.android.settings.inputmethod.InputMethodAndLanguageSettings"
- android:icon="@drawable/ic_settings_language"
- />
-
- <!-- Backup and reset -->
- <dashboard-tile
- android:id="@+id/privacy_settings"
- android:title="@string/privacy_settings"
- android:fragment="com.android.settings.PrivacySettings"
- android:icon="@drawable/ic_settings_backup"
- />
-
- </dashboard-category>
-
- <!-- SYSTEM -->
- <dashboard-category
- android:id="@+id/system_section"
- android:key="@string/category_key_system"
- android:title="@string/header_category_system" >
-
- <!-- Date & Time -->
- <dashboard-tile
- android:id="@+id/date_time_settings"
- android:title="@string/date_and_time_settings_title"
- android:fragment="com.android.settings.DateTimeSettings"
- android:icon="@drawable/ic_settings_date_time"
- />
-
- <!-- Accessibility feedback -->
- <dashboard-tile
- android:id="@+id/accessibility_settings"
- android:title="@string/accessibility_settings"
- android:fragment="com.android.settings.accessibility.AccessibilitySettings"
- android:icon="@drawable/ic_settings_accessibility"
- />
-
- <!-- Print -->
- <dashboard-tile
- android:id="@+id/print_settings"
- android:title="@string/print_settings"
- android:fragment="com.android.settings.print.PrintSettingsFragment"
- android:icon="@drawable/ic_settings_print"
- />
-
- <!-- Development -->
- <dashboard-tile
- android:id="@+id/development_settings"
- android:title="@string/development_settings_title"
- android:fragment="com.android.settings.DevelopmentSettings"
- android:icon="@drawable/ic_settings_development"
- />
-
- <!-- About Device -->
- <dashboard-tile
- android:id="@+id/about_settings"
- android:title="@string/about_settings"
- android:fragment="com.android.settings.DeviceInfoSettings"
- android:icon="@drawable/ic_settings_about"
- />
-
- </dashboard-category>
-
-</dashboard-categories>
diff --git a/res/xml/development_prefs.xml b/res/xml/development_prefs.xml
index 84c3cbf..57fdc36 100644
--- a/res/xml/development_prefs.xml
+++ b/res/xml/development_prefs.xml
@@ -60,10 +60,11 @@
android:summary="@string/runningservices_settings_summary"
android:fragment="com.android.settings.applications.RunningServices" />
- <com.android.settings.DropDownPreference
+ <DropDownPreference
android:key="night_mode"
android:title="@string/night_mode_title"
- android:summary="@string/night_mode_summary"
+ android:summary="%s"
+ android:persistent="false"
android:entries="@array/night_mode_entries"
android:entryValues="@array/night_mode_values" />
@@ -79,6 +80,12 @@
android:summary="@string/picture_color_mode_desc"
android:persistent="false" />
+ <ListPreference
+ android:key="select_webview_provider"
+ android:title="@string/select_webview_provider_title"
+ android:dialogTitle="@string/select_webview_provider_dialog_title"
+ android:summary="%s" />
+
<PreferenceCategory android:key="debug_debugging_category"
android:title="@string/debug_debugging_category">
@@ -340,6 +347,10 @@
android:entries="@array/app_process_limit_entries"
android:entryValues="@array/app_process_limit_values" />
+ <Preference
+ android:key="background_check"
+ android:title="@string/background_check_pref" />
+
<SwitchPreference
android:key="show_all_anrs"
android:title="@string/show_all_anrs"
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 60730a9..0456ace 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -91,23 +91,24 @@
android:summary="@string/tap_to_wake_summary"
android:persistent="false" />
- <com.android.settings.DropDownPreference
+ <DropDownPreference
android:key="font_size"
android:title="@string/title_font_size"
settings:keywords="@string/keywords_display_font_size"
- android:summary="@string/summary_font_size"
+ android:persistent="false"
+ android:summary="%s"
android:entries="@array/entries_font_size"
android:entryValues="@array/entryvalues_font_size" />
- <com.android.settings.DisplayDensityPreference
- android:key="display_density"
- android:title="@string/force_density_preference_title"
- android:summary="%s"
- settings:keywords="@string/force_density_keywords"
- android:persistent="false" />
+ <com.android.settings.display.ScreenZoomPreference
+ android:key="screen_zoom"
+ android:title="@string/screen_zoom_title"
+ settings:keywords="@string/screen_zoom_keywords" />
- <com.android.settings.DropDownPreference
+ <DropDownPreference
android:key="auto_rotate"
+ android:persistent="false"
+ android:summary="%s"
android:title="@string/display_auto_rotate_title" />
<PreferenceScreen
diff --git a/res/xml/installed_app_launch_settings.xml b/res/xml/installed_app_launch_settings.xml
index e48476f..dee56ef 100644
--- a/res/xml/installed_app_launch_settings.xml
+++ b/res/xml/installed_app_launch_settings.xml
@@ -20,9 +20,10 @@
<PreferenceCategory android:key="app_launch_domain_links"
android:title="@string/app_launch_domain_links_title">
- <com.android.settings.DropDownPreference
+ <DropDownPreference
android:key="app_link_state"
android:persistent="false"
+ android:summary="%s"
android:title="@string/app_launch_open_domain_urls_title" />
<com.android.settings.applications.AppDomainsPreference
diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml
index 2cd86f5..4ccc14a 100644
--- a/res/xml/location_settings.xml
+++ b/res/xml/location_settings.xml
@@ -27,19 +27,13 @@
android:summary="@string/location_mode_location_off_title" />
<!-- This preference category gets removed if there is no managed profile -->
- <PreferenceCategory
- android:key="managed_profile_location_category"
- android:title="@string/managed_profile_location_category">
-
- <Preference
- android:key="managed_profile_location_switch"
- android:title="@string/managed_profile_location_switch_title"
- android:summary="@string/managed_profile_location_switch_lockdown"
- android:persistent="false"
- android:enabled="false"
- android:selectable="false" />
-
- </PreferenceCategory>
+ <SwitchPreference
+ android:key="managed_profile_location_switch"
+ android:title="@string/managed_profile_location_switch_title"
+ android:summary="@string/managed_profile_location_switch_lockdown"
+ android:persistent="false"
+ android:enabled="false"
+ android:selectable="true" />
<PreferenceCategory
android:key="recent_location_requests"
diff --git a/res/xml/other_sound_settings.xml b/res/xml/other_sound_settings.xml
index cc88c3f..df113dc 100644
--- a/res/xml/other_sound_settings.xml
+++ b/res/xml/other_sound_settings.xml
@@ -56,15 +56,17 @@
android:persistent="false" />
<!-- Dock speaker plays -->
- <com.android.settings.DropDownPreference
+ <DropDownPreference
android:key="dock_audio_media"
android:title="@string/dock_audio_media_title"
+ android:summary="%s"
android:persistent="false" />
<!-- Emergency tone -->
- <com.android.settings.DropDownPreference
+ <DropDownPreference
android:key="emergency_tone"
android:title="@string/emergency_tone_title"
+ android:summary="%s"
android:persistent="false" />
</PreferenceScreen>
diff --git a/res/xml/privacy_settings.xml b/res/xml/privacy_settings.xml
index 721a3bf..e014420 100644
--- a/res/xml/privacy_settings.xml
+++ b/res/xml/privacy_settings.xml
@@ -54,10 +54,11 @@
android:fragment="com.android.settings.ResetNetwork" />
<!-- Factory reset -->
- <PreferenceScreen
+ <com.android.settings.RestrictedPreference
android:key="factory_reset"
android:title="@string/master_clear_title"
settings:keywords="@string/keywords_factory_data_reset"
+ settings:userRestriction="no_factory_reset"
android:fragment="com.android.settings.MasterClear" />
</PreferenceScreen>
diff --git a/res/xml/security_settings_misc.xml b/res/xml/security_settings_misc.xml
index 62b6fa3..41daa02 100644
--- a/res/xml/security_settings_misc.xml
+++ b/res/xml/security_settings_misc.xml
@@ -52,7 +52,7 @@
android:persistent="false"
android:fragment="com.android.settings.DeviceAdminSettings"/>
- <SwitchPreference android:key="toggle_install_applications"
+ <com.android.settings.RestrictedSwitchPreference android:key="toggle_install_applications"
android:title="@string/install_applications"
android:summaryOff="@string/install_unknown_applications"
android:summaryOn="@string/install_unknown_applications"
diff --git a/res/xml/topic_notification_settings.xml b/res/xml/topic_notification_settings.xml
index 6826070..d5f28b3 100644
--- a/res/xml/topic_notification_settings.xml
+++ b/res/xml/topic_notification_settings.xml
@@ -18,6 +18,13 @@
android:title="@string/topic_notifications_title"
android:key="topic_notification_settings">
+ <!-- Importance -->
+ <com.android.settings.notification.ImportanceSeekBarPreference
+ android:key="importance"
+ android:title="@string/notification_importance_title"
+ android:order="1"
+ android:persistent="false" />
+
<!-- Bypass DND -->
<SwitchPreference
android:key="bypass_dnd"
diff --git a/res/xml/wifi_advanced_settings.xml b/res/xml/wifi_advanced_settings.xml
index ed6cfbd..8d9a6cd 100644
--- a/res/xml/wifi_advanced_settings.xml
+++ b/res/xml/wifi_advanced_settings.xml
@@ -17,35 +17,6 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/wifi_advanced_titlebar">
- <!-- android:dependency="enable_wifi" -->
- <SwitchPreference
- android:key="notify_open_networks"
- android:title="@string/wifi_notify_open_networks"
- android:summary="@string/wifi_notify_open_networks_summary"
- android:persistent="false" />
-
- <ListPreference
- android:key="sleep_policy"
- android:title="@string/wifi_setting_sleep_policy_title"
- android:persistent="false"
- android:entries="@array/wifi_sleep_policy_entries"
- android:entryValues="@array/wifi_sleep_policy_values" />
-
- <com.android.settings.AppListSwitchPreference
- android:key="wifi_assistant"
- android:title="@string/wifi_automatically_connect_title"
- android:summary="@string/wifi_automatically_connect_summary"
- android:dialogTitle="@string/wifi_select_assistant_dialog_title"
- android:persistent="false" />
-
- <ListPreference
- android:key="frequency_band"
- android:title="@string/wifi_setting_frequency_band_title"
- android:summary="@string/wifi_setting_frequency_band_summary"
- android:persistent="false"
- android:entries="@array/wifi_frequency_band_entries"
- android:entryValues="@array/wifi_frequency_band_values" />
-
<Preference
android:key="install_credentials"
android:title="@string/wifi_install_credentials"
@@ -66,14 +37,4 @@
android:title="@string/wifi_menu_wps_pin"
android:persistent="false" />
- <Preference
- android:key="mac_address"
- android:title="@string/wifi_advanced_mac_address_title"
- android:layout="@layout/wifi_advance_layout" />
-
- <Preference
- android:key="current_ip_address"
- android:title="@string/wifi_advanced_ip_address_title"
- android:layout="@layout/wifi_advance_layout" />
-
-</PreferenceScreen>
+</PreferenceScreen>
diff --git a/res/xml/wifi_configure_settings.xml b/res/xml/wifi_configure_settings.xml
new file mode 100644
index 0000000..15e524a
--- /dev/null
+++ b/res/xml/wifi_configure_settings.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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/wifi_configure_titlebar">
+
+ <Preference
+ android:key="saved_networks"
+ android:title="@string/wifi_saved_access_points_label"
+ android:fragment="com.android.settings.wifi.SavedAccessPointsWifiSettings" />
+
+ <!-- android:dependency="enable_wifi" -->
+ <SwitchPreference
+ android:key="notify_open_networks"
+ android:title="@string/wifi_notify_open_networks"
+ android:summary="@string/wifi_notify_open_networks_summary"
+ android:persistent="false" />
+
+ <ListPreference
+ android:key="sleep_policy"
+ android:title="@string/wifi_setting_sleep_policy_title"
+ android:persistent="false"
+ android:entries="@array/wifi_sleep_policy_entries"
+ android:entryValues="@array/wifi_sleep_policy_values" />
+
+ <com.android.settings.AppListSwitchPreference
+ android:key="wifi_assistant"
+ android:title="@string/wifi_automatically_connect_title"
+ android:summary="@string/wifi_automatically_connect_summary"
+ android:dialogTitle="@string/wifi_select_assistant_dialog_title"
+ android:persistent="false" />
+
+ <ListPreference
+ android:key="frequency_band"
+ android:title="@string/wifi_setting_frequency_band_title"
+ android:summary="@string/wifi_setting_frequency_band_summary"
+ android:persistent="false"
+ android:entries="@array/wifi_frequency_band_entries"
+ android:entryValues="@array/wifi_frequency_band_values" />
+
+ <Preference
+ android:key="mac_address"
+ android:title="@string/wifi_advanced_mac_address_title"
+ android:layout="@layout/wifi_advance_layout" />
+
+ <Preference
+ android:key="current_ip_address"
+ android:title="@string/wifi_advanced_ip_address_title"
+ android:layout="@layout/wifi_advance_layout" />
+
+</PreferenceScreen>
diff --git a/res/xml/zen_mode_event_rule_settings.xml b/res/xml/zen_mode_event_rule_settings.xml
index 2519fc1..98e75ce 100644
--- a/res/xml/zen_mode_event_rule_settings.xml
+++ b/res/xml/zen_mode_event_rule_settings.xml
@@ -25,21 +25,24 @@
android:persistent="false" />
<!-- During events for -->
- <com.android.settings.DropDownPreference
+ <DropDownPreference
android:key="calendar"
android:title="@string/zen_mode_event_rule_calendar"
+ android:summary="%s"
android:persistent="false" />
<!-- Where reply is -->
- <com.android.settings.DropDownPreference
+ <DropDownPreference
android:key="reply"
android:title="@string/zen_mode_event_rule_reply"
+ android:summary="%s"
android:persistent="false" />
<!-- Zen mode -->
- <com.android.settings.DropDownPreference
+ <DropDownPreference
android:key="zen_mode"
android:title="@string/zen_mode_settings_title"
+ android:summary="%s"
android:persistent="false" />
</PreferenceScreen>
diff --git a/res/xml/zen_mode_external_rule_settings.xml b/res/xml/zen_mode_external_rule_settings.xml
index e244dc8..e3fafbd 100644
--- a/res/xml/zen_mode_external_rule_settings.xml
+++ b/res/xml/zen_mode_external_rule_settings.xml
@@ -37,8 +37,9 @@
android:persistent="false" />
<!-- Zen mode -->
- <com.android.settings.DropDownPreference
+ <DropDownPreference
android:key="zen_mode"
+ android:summary="%s"
android:title="@string/zen_mode_settings_title"
android:persistent="false" />
diff --git a/res/xml/zen_mode_priority_settings.xml b/res/xml/zen_mode_priority_settings.xml
index 6e324ce..6d9f36f 100644
--- a/res/xml/zen_mode_priority_settings.xml
+++ b/res/xml/zen_mode_priority_settings.xml
@@ -40,15 +40,17 @@
android:persistent="false"/>
<!-- Messages -->
- <com.android.settings.DropDownPreference
+ <DropDownPreference
android:key="messages"
android:title="@string/zen_mode_messages"
+ android:summary="%s"
android:persistent="false" />
<!-- Calls -->
- <com.android.settings.DropDownPreference
+ <DropDownPreference
android:key="calls"
android:title="@string/zen_mode_calls"
+ android:summary="%s"
android:persistent="false" />
<!-- Repeat callers -->
diff --git a/res/xml/zen_mode_schedule_rule_settings.xml b/res/xml/zen_mode_schedule_rule_settings.xml
index d808b10..3c62b5b 100644
--- a/res/xml/zen_mode_schedule_rule_settings.xml
+++ b/res/xml/zen_mode_schedule_rule_settings.xml
@@ -33,10 +33,11 @@
<!-- Start time/End time added and removed here! :-) -->
<!-- Zen mode -->
- <com.android.settings.DropDownPreference
+ <DropDownPreference
android:key="zen_mode"
android:title="@string/zen_mode_settings_title"
android:order="100"
+ android:summary="%s"
android:persistent="false" />
</PreferenceScreen>
diff --git a/src/com/android/settings/AirplaneModeVoiceActivity.java b/src/com/android/settings/AirplaneModeVoiceActivity.java
index e0649e4..21bfef2 100644
--- a/src/com/android/settings/AirplaneModeVoiceActivity.java
+++ b/src/com/android/settings/AirplaneModeVoiceActivity.java
@@ -16,7 +16,9 @@
package com.android.settings;
+import android.content.Context;
import android.content.Intent;
+import android.net.ConnectivityManager;
import android.provider.Settings;
import android.util.Log;
@@ -31,9 +33,10 @@
protected boolean onVoiceSettingInteraction(Intent intent) {
if (intent.hasExtra(Settings.EXTRA_AIRPLANE_MODE_ENABLED)) {
- Settings.Global.putInt(getContentResolver(),
- Settings.Global.AIRPLANE_MODE_ON,
- intent.getBooleanExtra(Settings.EXTRA_AIRPLANE_MODE_ENABLED, false) ? 1 : 0);
+ ConnectivityManager mgr = (ConnectivityManager) getSystemService(
+ Context.CONNECTIVITY_SERVICE);
+ mgr.setAirplaneMode(intent.getBooleanExtra(
+ Settings.EXTRA_AIRPLANE_MODE_ENABLED, false));
} else {
Log.v(TAG, "Missing airplane mode extra");
}
diff --git a/src/com/android/settings/ApnEditor.java b/src/com/android/settings/ApnEditor.java
index e785abb..20fb9ea 100644
--- a/src/com/android/settings/ApnEditor.java
+++ b/src/com/android/settings/ApnEditor.java
@@ -203,10 +203,22 @@
mFirstTime = icicle == null;
if (action.equals(Intent.ACTION_EDIT)) {
- mUri = intent.getData();
+ Uri uri = intent.getData();
+ if (!uri.isPathPrefixMatch(Telephony.Carriers.CONTENT_URI)) {
+ Log.e(TAG, "Edit request not for carrier table. Uri: " + uri);
+ finish();
+ return;
+ }
+ mUri = uri;
} else if (action.equals(Intent.ACTION_INSERT)) {
if (mFirstTime || icicle.getInt(SAVED_POS) == 0) {
- mUri = getContentResolver().insert(intent.getData(), new ContentValues());
+ Uri uri = intent.getData();
+ if (!uri.isPathPrefixMatch(Telephony.Carriers.CONTENT_URI)) {
+ Log.e(TAG, "Insert request not for carrier table. Uri: " + uri);
+ finish();
+ return;
+ }
+ mUri = getContentResolver().insert(uri, new ContentValues());
} else {
mUri = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI,
icicle.getInt(SAVED_POS));
diff --git a/src/com/android/settings/BugreportPreference.java b/src/com/android/settings/BugreportPreference.java
index 24af284..c3dd474 100644
--- a/src/com/android/settings/BugreportPreference.java
+++ b/src/com/android/settings/BugreportPreference.java
@@ -16,13 +16,31 @@
package com.android.settings;
+import android.app.ActivityManagerNative;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
-import android.os.SystemProperties;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.text.format.DateUtils;
import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.CheckedTextView;
+import android.widget.RadioButton;
+import android.widget.TextView;
+import android.widget.Toast;
public class BugreportPreference extends CustomDialogPreference {
+
+ private static final String TAG = "BugreportPreference";
+ private static final int BUGREPORT_DELAY_SECONDS = 3;
+
+ private CheckedTextView mInteractiveTitle;
+ private TextView mInteractiveSummary;
+ private CheckedTextView mFullTitle;
+ private TextView mFullSummary;
+
public BugreportPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -30,14 +48,67 @@
@Override
protected void onPrepareDialogBuilder(Builder builder, DialogInterface.OnClickListener listener) {
super.onPrepareDialogBuilder(builder, listener);
+
+ final View dialogView = View.inflate(getContext(), R.layout.bugreport_options_dialog, null);
+ mInteractiveTitle = (CheckedTextView) dialogView.findViewById(R.id.bugreport_option_interactive_title);
+ mInteractiveSummary = (TextView) dialogView.findViewById(R.id.bugreport_option_interactive_summary);
+ mFullTitle = (CheckedTextView) dialogView.findViewById(R.id.bugreport_option_full_title);
+ mFullSummary = (TextView) dialogView.findViewById(R.id.bugreport_option_full_summary);
+ final View.OnClickListener l = new View.OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ if (v == mFullTitle || v == mFullSummary) {
+ mInteractiveTitle.setChecked(false);
+ mFullTitle.setChecked(true);
+ }
+ if (v == mInteractiveTitle || v == mInteractiveSummary) {
+ mInteractiveTitle.setChecked(true);
+ mFullTitle.setChecked(false);
+ }
+ }
+ };
+ mInteractiveTitle.setOnClickListener(l);
+ mFullTitle.setOnClickListener(l);
+ mInteractiveSummary.setOnClickListener(l);
+ mFullSummary.setOnClickListener(l);
+
builder.setPositiveButton(com.android.internal.R.string.report, listener);
- builder.setMessage(com.android.internal.R.string.bugreport_message);
+ builder.setView(dialogView);
}
@Override
protected void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
- SystemProperties.set("ctl.start", "bugreport");
+
+ if (mFullTitle.isChecked()) {
+ Log.v(TAG, "Taking full bugreport right away");
+ takeBugreport(false);
+ } else {
+ Log.v(TAG, "Taking interactive bugreport in " + BUGREPORT_DELAY_SECONDS + "s");
+ // Add a little delay before executing, to give the user a chance to close
+ // the Settings activity before it takes a screenshot.
+ final Context context = getContext();
+ final String msg = context.getResources()
+ .getQuantityString(com.android.internal.R.plurals.bugreport_countdown,
+ BUGREPORT_DELAY_SECONDS, BUGREPORT_DELAY_SECONDS);
+ Log.v(TAG, msg);
+ Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ takeBugreport(true);
+ }
+ }, BUGREPORT_DELAY_SECONDS * DateUtils.SECOND_IN_MILLIS);
+ }
+ }
+ }
+
+ private void takeBugreport(boolean progress) {
+ try {
+ ActivityManagerNative.getDefault().requestBugReport(progress);
+ } catch (RemoteException e) {
+ Log.e(TAG, "error taking bugreport (progress=" + progress + ")", e);
}
}
}
diff --git a/src/com/android/settings/ChooseLockGeneric.java b/src/com/android/settings/ChooseLockGeneric.java
index 65f0ba6..73f8c46 100644
--- a/src/com/android/settings/ChooseLockGeneric.java
+++ b/src/com/android/settings/ChooseLockGeneric.java
@@ -220,13 +220,17 @@
&& !dpm.getDoNotAskCredentialsOnBoot()) {
mEncryptionRequestQuality = quality;
mEncryptionRequestDisabled = disabled;
+ // Get the intent that the encryption interstitial should start for creating
+ // the new unlock method.
+ Intent unlockMethodIntent = getIntentForUnlockMethod(quality, disabled);
final Context context = getActivity();
// If accessibility is enabled and the user hasn't seen this dialog before, set the
// default state to agree with that which is compatible with accessibility
// (password not required).
final boolean accEn = AccessibilityManager.getInstance(context).isEnabled();
final boolean required = mLockPatternUtils.isCredentialRequiredToDecrypt(!accEn);
- Intent intent = getEncryptionInterstitialIntent(context, quality, required);
+ Intent intent = getEncryptionInterstitialIntent(context, quality, required,
+ unlockMethodIntent);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT,
mForFingerprint);
startActivityForResult(intent, ENABLE_ENCRYPTION_REQUEST);
@@ -244,14 +248,12 @@
mPasswordConfirmed = true;
mUserPassword = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
updatePreferencesOrFinish();
- } else if (requestCode == ENABLE_ENCRYPTION_REQUEST
- && resultCode == Activity.RESULT_OK) {
- mRequirePassword = data.getBooleanExtra(
- EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
- updateUnlockMethodAndFinish(mEncryptionRequestQuality, mEncryptionRequestDisabled);
- } else if (requestCode == CHOOSE_LOCK_REQUEST) {
- getActivity().setResult(resultCode, data);
- finish();
+ } else if (requestCode == CHOOSE_LOCK_REQUEST
+ || requestCode == ENABLE_ENCRYPTION_REQUEST) {
+ if (resultCode != RESULT_CANCELED) {
+ getActivity().setResult(resultCode, data);
+ finish();
+ }
} else {
getActivity().setResult(Activity.RESULT_CANCELED);
finish();
@@ -451,8 +453,9 @@
}
protected Intent getEncryptionInterstitialIntent(Context context, int quality,
- boolean required) {
- return EncryptionInterstitial.createStartIntent(context, quality, required);
+ boolean required, Intent unlockMethodIntent) {
+ return EncryptionInterstitial.createStartIntent(context, quality, required,
+ unlockMethodIntent);
}
/**
@@ -471,34 +474,13 @@
}
quality = upgradeQuality(quality);
+ Intent intent = getIntentForUnlockMethod(quality, disabled);
+ if (intent != null) {
+ startActivityForResult(intent, CHOOSE_LOCK_REQUEST);
+ return;
+ }
- final Context context = getActivity();
- if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
- int minLength = mDPM.getPasswordMinimumLength(null);
- if (minLength < MIN_PASSWORD_LENGTH) {
- minLength = MIN_PASSWORD_LENGTH;
- }
- final int maxLength = mDPM.getPasswordMaximumLength(quality);
- Intent intent;
- if (mHasChallenge) {
- intent = getLockPasswordIntent(context, quality, minLength,
- maxLength, mRequirePassword, mChallenge, mUserId);
- } else {
- intent = getLockPasswordIntent(context, quality, minLength,
- maxLength, mRequirePassword, mUserPassword, mUserId);
- }
- startActivityForResult(intent, CHOOSE_LOCK_REQUEST);
- } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
- Intent intent;
- if (mHasChallenge) {
- intent = getLockPatternIntent(context, mRequirePassword,
- mChallenge, mUserId);
- } else {
- intent = getLockPatternIntent(context, mRequirePassword,
- mUserPassword, mUserId);
- }
- startActivityForResult(intent, CHOOSE_LOCK_REQUEST);
- } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
+ if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
mChooseLockSettingsHelper.utils().clearLock(mUserId);
mChooseLockSettingsHelper.utils().setLockScreenDisabled(disabled, mUserId);
removeAllFingerprintTemplatesAndFinish();
@@ -508,6 +490,34 @@
}
}
+ private Intent getIntentForUnlockMethod(int quality, boolean disabled) {
+ Intent intent = null;
+ final Context context = getActivity();
+ if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
+ int minLength = mDPM.getPasswordMinimumLength(null);
+ if (minLength < MIN_PASSWORD_LENGTH) {
+ minLength = MIN_PASSWORD_LENGTH;
+ }
+ final int maxLength = mDPM.getPasswordMaximumLength(quality);
+ if (mHasChallenge) {
+ intent = getLockPasswordIntent(context, quality, minLength,
+ maxLength, mRequirePassword, mChallenge, mUserId);
+ } else {
+ intent = getLockPasswordIntent(context, quality, minLength,
+ maxLength, mRequirePassword, mUserPassword, mUserId);
+ }
+ } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
+ if (mHasChallenge) {
+ intent = getLockPatternIntent(context, mRequirePassword,
+ mChallenge, mUserId);
+ } else {
+ intent = getLockPatternIntent(context, mRequirePassword,
+ mUserPassword, mUserId);
+ }
+ }
+ return intent;
+ }
+
private void removeAllFingerprintTemplatesAndFinish() {
if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()
&& mFingerprintManager.getEnrolledFingerprints().size() > 0) {
diff --git a/src/com/android/settings/ChooseLockSettingsHelper.java b/src/com/android/settings/ChooseLockSettingsHelper.java
index 4c3fb7b..ab81455 100644
--- a/src/com/android/settings/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/ChooseLockSettingsHelper.java
@@ -21,6 +21,7 @@
import android.app.Fragment;
import android.app.admin.DevicePolicyManager;
import android.content.Intent;
+import android.content.IntentSender;
import com.android.internal.widget.LockPatternUtils;
@@ -114,6 +115,27 @@
/**
* If a pattern, password or PIN exists, prompt the user before allowing them to change it.
+ *
+ * @param title title of the confirmation screen; shown in the action bar
+ * @param header header of the confirmation screen; shown as large text
+ * @param description description of the confirmation screen
+ * @param returnCredentials if true, put credentials into intent. Note that if this is true,
+ * this can only be called internally.
+ * @param external specifies whether this activity is launched externally, meaning that it will
+ * get a dark theme and allow fingerprint authentication
+ * @param userId The userId for whom the lock should be confirmed.
+ * @return true if one exists and we launched an activity to confirm it
+ * @see Activity#onActivityResult(int, int, android.content.Intent)
+ */
+ boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
+ @Nullable CharSequence header, @Nullable CharSequence description,
+ boolean returnCredentials, boolean external, int userId) {
+ return launchConfirmationActivity(request, title, header, description,
+ returnCredentials, external, false, 0, Utils.getSameOwnerUserId(mActivity, userId));
+ }
+
+ /**
+ * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
* @param message optional message to display about the action about to be done
* @param details optional detail message to display
* @param challenge a challenge to be verified against the device credential.
@@ -175,8 +197,18 @@
if (external) {
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
if (mFragment != null) {
+ IntentSender intentSender = mFragment.getActivity().getIntent()
+ .getParcelableExtra(Intent.EXTRA_INTENT);
+ if (intentSender != null) {
+ intent.putExtra(Intent.EXTRA_INTENT, intentSender);
+ }
mFragment.startActivity(intent);
} else {
+ IntentSender intentSender = mActivity.getIntent()
+ .getParcelableExtra(Intent.EXTRA_INTENT);
+ if (intentSender != null) {
+ intent.putExtra(Intent.EXTRA_INTENT, intentSender);
+ }
mActivity.startActivity(intent);
}
} else {
diff --git a/src/com/android/settings/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/ConfirmDeviceCredentialActivity.java
index 86935c3..c4587eb 100644
--- a/src/com/android/settings/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/ConfirmDeviceCredentialActivity.java
@@ -20,7 +20,11 @@
import android.app.Activity;
import android.app.KeyguardManager;
import android.content.Intent;
+import android.os.Binder;
import android.os.Bundle;
+import android.os.Process;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.util.Log;
/**
@@ -30,6 +34,9 @@
public class ConfirmDeviceCredentialActivity extends Activity {
public static final String TAG = ConfirmDeviceCredentialActivity.class.getSimpleName();
+ public static class InternalActivity extends ConfirmDeviceCredentialActivity {
+ }
+
public static Intent createIntent(CharSequence title, CharSequence details) {
Intent intent = new Intent();
intent.setClassName("com.android.settings",
@@ -57,13 +64,24 @@
Intent intent = getIntent();
String title = intent.getStringExtra(KeyguardManager.EXTRA_TITLE);
String details = intent.getStringExtra(KeyguardManager.EXTRA_DESCRIPTION);
-
+ int userId = Utils.getEffectiveUserId(this);
+ if (isInternalActivity()) {
+ int givenUserId = intent.getIntExtra(Intent.EXTRA_USER_ID, userId);
+ UserManager userManager = UserManager.get(this);
+ if (userManager.isSameProfileGroup(givenUserId, userId)) {
+ userId = givenUserId;
+ }
+ }
ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this);
if (!helper.launchConfirmationActivity(0 /* request code */, null /* title */, title,
- details, false /* returnCredentials */, true /* isExternal */)) {
+ details, false /* returnCredentials */, true /* isExternal */, userId)) {
Log.d(TAG, "No pattern, password or PIN set.");
setResult(Activity.RESULT_OK);
}
finish();
}
+
+ private boolean isInternalActivity() {
+ return this instanceof ConfirmDeviceCredentialActivity.InternalActivity;
+ }
}
diff --git a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
index 32ad317..e04f86f 100644
--- a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
+++ b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
@@ -18,6 +18,7 @@
import android.annotation.Nullable;
import android.content.Intent;
+import android.content.IntentSender;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
@@ -124,4 +125,16 @@
public void startEnterAnimation() {
}
+
+ protected void checkForPendingIntent() {
+ IntentSender intentSender = getActivity().getIntent()
+ .getParcelableExtra(Intent.EXTRA_INTENT);
+ if (intentSender != null) {
+ try {
+ getActivity().startIntentSenderForResult(intentSender, -1, null, 0, 0, 0);
+ } catch (IntentSender.SendIntentException e) {
+ /* ignore */
+ }
+ }
+ }
}
diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java
index 7ef6a57..53555e0 100644
--- a/src/com/android/settings/ConfirmLockPassword.java
+++ b/src/com/android/settings/ConfirmLockPassword.java
@@ -20,6 +20,7 @@
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentSender;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CountDownTimer;
@@ -405,6 +406,7 @@
mPasswordEntryInputDisabler.setInputEnabled(true);
if (matched) {
startDisappearAnimation(intent);
+ checkForPendingIntent();
} else {
if (timeoutMs > 0) {
long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
diff --git a/src/com/android/settings/ConfirmLockPattern.java b/src/com/android/settings/ConfirmLockPattern.java
index 44e74c9..6331290 100644
--- a/src/com/android/settings/ConfirmLockPattern.java
+++ b/src/com/android/settings/ConfirmLockPattern.java
@@ -18,6 +18,7 @@
import android.app.Activity;
import android.content.Intent;
+import android.content.IntentSender;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CountDownTimer;
@@ -473,6 +474,7 @@
mLockPatternView.setEnabled(true);
if (matched) {
startDisappearAnimation(intent);
+ checkForPendingIntent();
} else {
if (timeoutMs > 0) {
long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
diff --git a/src/com/android/settings/CryptKeeper.java b/src/com/android/settings/CryptKeeper.java
index 1b37066..594cd38 100644
--- a/src/com/android/settings/CryptKeeper.java
+++ b/src/com/android/settings/CryptKeeper.java
@@ -799,6 +799,8 @@
// Asynchronously throw up the IME, since there are issues with requesting it to be shown
// immediately.
if (mLockPatternView == null && !mCooldown) {
+ getWindow().setSoftInputMode(
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
mHandler.postDelayed(new Runnable() {
@Override public void run() {
imm.showSoftInputUnchecked(0, null);
diff --git a/src/com/android/settings/CustomListPreference.java b/src/com/android/settings/CustomListPreference.java
index 1d49165..ce37c14 100644
--- a/src/com/android/settings/CustomListPreference.java
+++ b/src/com/android/settings/CustomListPreference.java
@@ -44,6 +44,8 @@
public static class CustomListPreferenceDialogFragment extends ListPreferenceDialogFragment {
+ private int mClickedDialogEntryIndex;
+
public static ListPreferenceDialogFragment newInstance(String key) {
final ListPreferenceDialogFragment fragment = new CustomListPreferenceDialogFragment();
final Bundle b = new Bundle(1);
@@ -59,12 +61,35 @@
@Override
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
super.onPrepareDialogBuilder(builder);
- getCustomizablePreference().onPrepareDialogBuilder(builder, this);
+ mClickedDialogEntryIndex = getCustomizablePreference()
+ .findIndexOfValue(getCustomizablePreference().getValue());
+ getCustomizablePreference().onPrepareDialogBuilder(builder,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ mClickedDialogEntryIndex = which;
+
+ /*
+ * Clicking on an item simulates the positive button
+ * click, and dismisses the dialog.
+ */
+ CustomListPreferenceDialogFragment.this.onClick(dialog,
+ DialogInterface.BUTTON_POSITIVE);
+ dialog.dismiss();
+ }
+ });
}
@Override
public void onDialogClosed(boolean positiveResult) {
getCustomizablePreference().onDialogClosed(positiveResult);
+ final ListPreference preference = getCustomizablePreference();
+ if (positiveResult && mClickedDialogEntryIndex >= 0 &&
+ preference.getEntryValues() != null) {
+ String value = preference.getEntryValues()[mClickedDialogEntryIndex].toString();
+ if (preference.callChangeListener(value)) {
+ preference.setValue(value);
+ }
+ }
}
}
}
diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java
index 3fe0a46..38376e4 100644
--- a/src/com/android/settings/DataUsageSummary.java
+++ b/src/com/android/settings/DataUsageSummary.java
@@ -99,6 +99,8 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.telephony.PhoneConstants;
import com.android.settings.dashboard.SummaryLoader;
+import com.android.settings.dashboard.conditional.BackgroundDataCondition;
+import com.android.settings.dashboard.conditional.ConditionManager;
import com.android.settings.drawable.InsetBoundsDrawable;
import com.android.settings.net.DataUsageMeteredSettings;
import com.android.settings.search.BaseSearchIndexProvider;
@@ -1100,6 +1102,8 @@
public void setRestrictBackground(boolean restrictBackground) {
mPolicyManager.setRestrictBackground(restrictBackground);
updateMenuTitles();
+ ConditionManager.get(getContext()).getCondition(BackgroundDataCondition.class)
+ .refreshState();
}
private boolean getAppRestrictBackground() {
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index c25d2d3..9490fef 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -59,6 +59,7 @@
import android.provider.Settings;
import android.provider.Settings.Global;
import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
@@ -66,16 +67,20 @@
import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import android.util.Log;
-import android.view.HardwareRenderer;
+import android.view.ThreadedRenderer;
import android.view.IWindowManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
+import android.webkit.IWebViewUpdateService;
+import android.webkit.WebViewProviderInfo;
import android.widget.Switch;
import android.widget.TextView;
+import com.android.internal.app.LocalePicker;
import com.android.internal.logging.MetricsLogger;
+import com.android.settings.applications.BackgroundCheckSummary;
import com.android.settings.fuelgauge.InactiveApps;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
@@ -109,6 +114,7 @@
private static final String ENABLE_TERMINAL = "enable_terminal";
private static final String KEEP_SCREEN_ON = "keep_screen_on";
private static final String BT_HCI_SNOOP_LOG = "bt_hci_snoop_log";
+ private static final String WEBVIEW_PROVIDER_KEY = "select_webview_provider";
private static final String ENABLE_OEM_UNLOCK = "oem_unlock_enable";
private static final String HDCP_CHECKING_KEY = "hdcp_checking";
private static final String HDCP_CHECKING_PROPERTY = "persist.sys.hdcp_checking";
@@ -170,6 +176,8 @@
= "immediately_destroy_activities";
private static final String APP_PROCESS_LIMIT_KEY = "app_process_limit";
+ private static final String BACKGROUND_CHECK_KEY = "background_check";
+
private static final String SHOW_ALL_ANRS_KEY = "show_all_anrs";
private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
@@ -250,6 +258,7 @@
private ListPreference mAnimatorDurationScale;
private ListPreference mOverlayDisplayDevices;
private ListPreference mOpenGLTraces;
+ private ListPreference mWebViewProvider;
private ListPreference mSimulateColorSpace;
@@ -386,6 +395,7 @@
mMobileDataAlwaysOn = findAndInitSwitchPref(MOBILE_DATA_ALWAYS_ON);
mLogdSize = addListPreference(SELECT_LOGD_SIZE_KEY);
mUsbConfiguration = addListPreference(USB_CONFIGURATION_KEY);
+ mWebViewProvider = addListPreference(WEBVIEW_PROVIDER_KEY);
mWindowAnimationScale = addListPreference(WINDOW_ANIMATION_SCALE_KEY);
mTransitionAnimationScale = addListPreference(TRANSITION_ANIMATION_SCALE_KEY);
@@ -458,6 +468,7 @@
removePreference(KEY_COLOR_MODE);
mColorModePreference = null;
}
+ updateWebViewProviderOptions();
}
private ListPreference addListPreference(String prefKey) {
@@ -666,6 +677,7 @@
updateSimulateColorSpace();
updateUSBAudioOptions();
updateForceResizableOptions();
+ updateWebViewProviderOptions();
}
private void resetDangerousOptions() {
@@ -694,6 +706,39 @@
pokeSystemProperties();
}
+ private void updateWebViewProviderOptions() {
+ IWebViewUpdateService webViewUpdateService =
+ IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
+ try {
+ WebViewProviderInfo[] providers = webViewUpdateService.getValidWebViewPackages();
+ if (providers == null) {
+ Log.e(TAG, "No WebView providers available");
+ return;
+ }
+ String[] options = new String[providers.length];
+ String[] values = new String[providers.length];
+ for(int n = 0; n < providers.length; n++) {
+ options[n] = providers[n].description;
+ values[n] = providers[n].packageName;
+ }
+ mWebViewProvider.setEntries(options);
+ mWebViewProvider.setEntryValues(values);
+
+ String value = webViewUpdateService.getCurrentWebViewPackageName();
+ if (value == null) {
+ value = "";
+ }
+
+ for (int i = 0; i < values.length; i++) {
+ if (value.contentEquals(values[i])) {
+ mWebViewProvider.setValueIndex(i);
+ return;
+ }
+ }
+ } catch(RemoteException e) {
+ }
+ }
+
private void updateHdcpValues() {
ListPreference hdcpChecking = (ListPreference) findPreference(HDCP_CHECKING_KEY);
if (hdcpChecking != null) {
@@ -733,6 +778,18 @@
mBtHciSnoopLog.isChecked() ? 1 : 0);
}
+ private void writeWebViewProviderOptions(Object newValue) {
+ IWebViewUpdateService webViewUpdateService =
+ IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
+
+ try {
+ webViewUpdateService.changeProviderAndSetting(
+ newValue == null ? "" : newValue.toString());
+ updateWebViewProviderOptions();
+ } catch(RemoteException e) {
+ }
+ }
+
private void writeDebuggerOptions() {
try {
ActivityManagerNative.getDefault().setDebugApp(
@@ -1023,7 +1080,7 @@
}
private void updateTrackFrameTimeOptions() {
- String value = SystemProperties.get(HardwareRenderer.PROFILE_PROPERTY);
+ String value = SystemProperties.get(ThreadedRenderer.PROFILE_PROPERTY);
if (value == null) {
value = "";
}
@@ -1041,7 +1098,7 @@
}
private void writeTrackFrameTimeOptions(Object newValue) {
- SystemProperties.set(HardwareRenderer.PROFILE_PROPERTY,
+ SystemProperties.set(ThreadedRenderer.PROFILE_PROPERTY,
newValue == null ? "" : newValue.toString());
pokeSystemProperties();
updateTrackFrameTimeOptions();
@@ -1049,7 +1106,7 @@
private void updateShowNonRectClipOptions() {
String value = SystemProperties.get(
- HardwareRenderer.DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY);
+ ThreadedRenderer.DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY);
if (value == null) {
value = "hide";
}
@@ -1067,7 +1124,7 @@
}
private void writeShowNonRectClipOptions(Object newValue) {
- SystemProperties.set(HardwareRenderer.DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY,
+ SystemProperties.set(ThreadedRenderer.DEBUG_SHOW_NON_RECTANGULAR_CLIP_PROPERTY,
newValue == null ? "" : newValue.toString());
pokeSystemProperties();
updateShowNonRectClipOptions();
@@ -1075,28 +1132,28 @@
private void updateShowHwScreenUpdatesOptions() {
updateSwitchPreference(mShowHwScreenUpdates,
- SystemProperties.getBoolean(HardwareRenderer.DEBUG_DIRTY_REGIONS_PROPERTY, false));
+ SystemProperties.getBoolean(ThreadedRenderer.DEBUG_DIRTY_REGIONS_PROPERTY, false));
}
private void writeShowHwScreenUpdatesOptions() {
- SystemProperties.set(HardwareRenderer.DEBUG_DIRTY_REGIONS_PROPERTY,
+ SystemProperties.set(ThreadedRenderer.DEBUG_DIRTY_REGIONS_PROPERTY,
mShowHwScreenUpdates.isChecked() ? "true" : null);
pokeSystemProperties();
}
private void updateShowHwLayersUpdatesOptions() {
updateSwitchPreference(mShowHwLayersUpdates, SystemProperties.getBoolean(
- HardwareRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY, false));
+ ThreadedRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY, false));
}
private void writeShowHwLayersUpdatesOptions() {
- SystemProperties.set(HardwareRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY,
+ SystemProperties.set(ThreadedRenderer.DEBUG_SHOW_LAYERS_UPDATES_PROPERTY,
mShowHwLayersUpdates.isChecked() ? "true" : null);
pokeSystemProperties();
}
private void updateDebugHwOverdrawOptions() {
- String value = SystemProperties.get(HardwareRenderer.DEBUG_OVERDRAW_PROPERTY);
+ String value = SystemProperties.get(ThreadedRenderer.DEBUG_OVERDRAW_PROPERTY);
if (value == null) {
value = "";
}
@@ -1114,7 +1171,7 @@
}
private void writeDebugHwOverdrawOptions(Object newValue) {
- SystemProperties.set(HardwareRenderer.DEBUG_OVERDRAW_PROPERTY,
+ SystemProperties.set(ThreadedRenderer.DEBUG_OVERDRAW_PROPERTY,
newValue == null ? "" : newValue.toString());
pokeSystemProperties();
updateDebugHwOverdrawOptions();
@@ -1718,6 +1775,8 @@
writeForceResizableOptions();
} else if (INACTIVE_APPS_KEY.equals(preference.getKey())) {
startInactiveAppsFragment();
+ } else if (BACKGROUND_CHECK_KEY.equals(preference.getKey())) {
+ startBackgroundCheckFragment();
} else {
return super.onPreferenceTreeClick(preference);
}
@@ -1731,6 +1790,12 @@
null, R.string.inactive_apps_title, null, null, 0);
}
+ private void startBackgroundCheckFragment() {
+ ((SettingsActivity) getActivity()).startPreferencePanel(
+ BackgroundCheckSummary.class.getName(),
+ null, R.string.background_check_title, null, null, 0);
+ }
+
private boolean showKeyguardConfirmation(Resources resources, int requestCode) {
return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(
requestCode, resources.getString(R.string.oem_unlock_enable));
@@ -1743,6 +1808,9 @@
updateHdcpValues();
pokeSystemProperties();
return true;
+ } else if (preference == mWebViewProvider) {
+ writeWebViewProviderOptions(newValue);
+ return true;
} else if (preference == mLogdSize) {
writeLogdSizeOption(newValue);
return true;
diff --git a/src/com/android/settings/DisplayDensityPreference.java b/src/com/android/settings/DisplayDensityPreference.java
deleted file mode 100644
index 85f2fb2..0000000
--- a/src/com/android/settings/DisplayDensityPreference.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2015 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;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.os.AsyncTask;
-import android.os.RemoteException;
-import android.support.annotation.ArrayRes;
-import android.support.v7.preference.ListPreference;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.util.MathUtils;
-import android.view.Display;
-import android.view.IWindowManager;
-import android.view.WindowManagerGlobal;
-
-import com.android.settings.R;
-
-import java.util.Arrays;
-
-/**
- * Preference for changing the density of the display on which the preference
- * is visible.
- */
-public class DisplayDensityPreference extends ListPreference {
- private static final String LOG_TAG = "DisplayDensityPreference";
-
- /** Minimum increment between density scales. */
- private static final float MIN_SCALE_INTERVAL = 0.09f;
-
- /** Minimum density scale. This is available on all devices. */
- private static final float MIN_SCALE = 0.85f;
-
- /** Maximum density scale. The actual scale used depends on the device. */
- private static final float MAX_SCALE = 1.50f;
-
- /** Sentinel value for "normal" scaling (effectively disabled). */
- private static final int DENSITY_VALUE_NORMAL = -1;
-
- /** Summary used for "normal" scale. */
- private static final int DENSITY_SUMMARY_NORMAL = R.string.force_density_summary_normal;
-
- /**
- * Summaries for scales smaller than "normal" in order of smallest to
- * largest.
- */
- private static final int[] SMALLER_SUMMARIES = new int[] {
- R.string.force_density_summary_small
- };
-
- /**
- * Summaries for scales larger than "normal" in order of smallest to
- * largest.
- */
- private static final int[] LARGER_SUMMARIES = new int[] {
- R.string.force_density_summary_large,
- R.string.force_density_summary_very_large,
- R.string.force_density_summary_extremely_large,
- };
-
- /**
- * Minimum allowed screen dimension, corresponds to resource qualifiers
- * "small" or "sw320dp". This value must be at least the minimum screen
- * size required by the CDD so that we meet developer expectations.
- */
- private static final int MIN_DIMENSION_DP = 320;
-
- /** The ID of the display affected by this preference. */
- private int mDisplayId = Display.DEFAULT_DISPLAY;
-
- public DisplayDensityPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- if (!prepareList()) {
- setEnabled(false);
- }
- }
-
- private boolean prepareList() {
- final int initialDensity = getInitialDisplayDensity(mDisplayId);
- if (initialDensity <= 0) {
- return false;
- }
-
- final Resources res = getContext().getResources();
- final DisplayMetrics metrics = res.getDisplayMetrics();
- final int currentDensity = metrics.densityDpi;
- int currentDensityIndex = -1;
-
- // Compute number of "larger" and "smaller" scales for this display.
- final int minDimensionPx = Math.min(metrics.widthPixels, metrics.heightPixels);
- final int maxDensity = DisplayMetrics.DENSITY_MEDIUM * minDimensionPx / MIN_DIMENSION_DP;
- final float maxScale = Math.min(MAX_SCALE, maxDensity / (float) initialDensity);
- final float minScale = MIN_SCALE;
- final int numLarger = (int) MathUtils.constrain((maxScale - 1) / MIN_SCALE_INTERVAL,
- 0, LARGER_SUMMARIES.length);
- final int numSmaller = (int) MathUtils.constrain((1 - minScale) / MIN_SCALE_INTERVAL,
- 0, SMALLER_SUMMARIES.length);
-
- CharSequence[] values = new CharSequence[1 + numSmaller + numLarger];
- CharSequence[] entries = new CharSequence[values.length];
- int curIndex = 0;
-
- if (numSmaller > 0) {
- final float interval = (1 - minScale) / numSmaller;
- for (int i = numSmaller - 1; i >= 0; i--) {
- final int density = (int) (initialDensity * (1 - (i + 1) * interval));
- if (currentDensity == density) {
- currentDensityIndex = curIndex;
- }
- values[curIndex] = Integer.toString(density);
- entries[curIndex] = res.getText(SMALLER_SUMMARIES[i]);
- curIndex++;
- }
- }
-
- if (currentDensity == initialDensity) {
- currentDensityIndex = curIndex;
- }
- values[curIndex] = Integer.toString(DENSITY_VALUE_NORMAL);
- entries[curIndex] = res.getText(DENSITY_SUMMARY_NORMAL);
- curIndex++;
-
- if (numLarger > 0) {
- final float interval = (maxScale - 1) / numLarger;
- for (int i = 0; i < numLarger; i++) {
- final int density = (int) (initialDensity * (1 + (i + 1) * interval));
- if (currentDensity == density) {
- currentDensityIndex = curIndex;
- }
- values[curIndex] = Integer.toString(density);
- entries[curIndex] = res.getText(LARGER_SUMMARIES[i]);
- curIndex++;
- }
- }
-
- final int displayIndex;
- if (currentDensityIndex >= 0) {
- displayIndex = currentDensityIndex;
- } else {
- // We don't understand the current density. Must have been set by
- // someone else. Make room for another entry...
- values = Arrays.copyOf(values, values.length + 1);
- values[curIndex] = res.getString(R.string.force_density_summary_custom, currentDensity);
-
- entries = Arrays.copyOf(entries, values.length + 1);
- entries[curIndex] = Integer.toString(currentDensity);
-
- displayIndex = curIndex;
- }
-
- super.setEntryValues(values);
- super.setEntries(entries);
-
- setValueIndex(displayIndex);
-
- return true;
- }
-
- @Override
- public boolean callChangeListener(Object newValue) {
- final boolean allowed = super.callChangeListener(newValue);
- if (allowed) {
- final int density = Integer.parseInt((String) newValue);
- setForcedDisplayDensity(mDisplayId, density);
- }
-
- return allowed;
- }
-
- @Override
- public void setEntries(CharSequence[] entries) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setEntries(@ArrayRes int entriesResId) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setEntryValues(CharSequence[] entryValues) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void setEntryValues(@ArrayRes int entryValuesResId) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns the initial density for the specified display.
- *
- * @param displayId the identifier of the display
- * @return the initial density of the specified display, or {@code -1} if
- * the display does not exist or the density could not be obtained
- */
- private static int getInitialDisplayDensity(int displayId) {
- try {
- IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
- return wm.getInitialDisplayDensity(displayId);
- } catch (RemoteException exc) {
- return -1;
- }
- }
-
- /**
- * Asynchronously applies display density changes to the specified display.
- *
- * @param displayId the identifier of the display to modify
- * @param density the density to force for the specified display, or <= 0
- * to clear any previously forced density
- */
- private static void setForcedDisplayDensity(final int displayId, final int density) {
- AsyncTask.execute(new Runnable() {
- @Override
- public void run() {
- try {
- IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
- if (density <= 0) {
- wm.clearForcedDisplayDensity(displayId);
- } else {
- wm.setForcedDisplayDensity(displayId, density);
- }
- } catch (RemoteException exc) {
- Log.w(LOG_TAG, "Unable to save forced display density setting");
- }
- }
- });
- }
-}
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index 0d52aa7..6d99a35 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -33,11 +33,13 @@
import android.provider.SearchIndexableResource;
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.text.TextUtils;
import android.util.Log;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.view.RotationPolicy;
import com.android.settings.dashboard.SummaryLoader;
@@ -76,7 +78,6 @@
private static final String KEY_CAMERA_GESTURE = "camera_gesture";
private static final String KEY_CAMERA_DOUBLE_TAP_POWER_GESTURE
= "camera_double_tap_power_gesture";
- private static final String KEY_DISPLAY_DENSITY = "display_density";
private DropDownPreference mFontSizePref;
@@ -214,9 +215,6 @@
mNightModePreference.setValue(String.valueOf(currentNightMode));
mNightModePreference.setOnPreferenceChangeListener(this);
}
-
- final Preference displayDensity = findPreference(KEY_DISPLAY_DENSITY);
- displayDensity.setOnPreferenceChangeListener(this);
}
private static boolean allowAllRotations(Context context) {
diff --git a/src/com/android/settings/DropDownPreference.java b/src/com/android/settings/DropDownPreference.java
deleted file mode 100644
index 3088497..0000000
--- a/src/com/android/settings/DropDownPreference.java
+++ /dev/null
@@ -1,118 +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;
-
-import android.content.Context;
-import android.support.v7.preference.ListPreference;
-import android.support.v7.preference.PreferenceViewHolder;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemSelectedListener;
-import android.widget.ArrayAdapter;
-import android.widget.Spinner;
-
-public class DropDownPreference extends ListPreference {
-
- private final Context mContext;
- private final ArrayAdapter<String> mAdapter;
- private final Spinner mSpinner;
-
- public DropDownPreference(Context context) {
- this(context, null);
- }
-
- public DropDownPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- mContext = context;
- mAdapter = new ArrayAdapter<String>(mContext,
- android.R.layout.simple_spinner_dropdown_item);
-
- mSpinner = new Spinner(mContext);
-
- mSpinner.setVisibility(View.INVISIBLE);
- mSpinner.setAdapter(mAdapter);
- mSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
- if (position >= 0) {
- String value = getEntryValues()[position].toString();
- if (!value.equals(getValue()) && callChangeListener(value)) {
- setValue(value);
- }
- }
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- // noop
- }
- });
- setPersistent(false);
- updateEntries();
- }
-
- @Override
- protected void onClick() {
- mSpinner.performClick();
- }
-
- public void setDropDownWidth(int dimenResId) {
- mSpinner.setDropDownWidth(mContext.getResources().getDimensionPixelSize(dimenResId));
- }
-
- @Override
- public void setEntries(CharSequence[] entries) {
- super.setEntries(entries);
- updateEntries();
- }
-
- private void updateEntries() {
- mAdapter.clear();
- if (getEntries() != null) {
- for (CharSequence c : getEntries()) {
- mAdapter.add(c.toString());
- }
- }
- }
-
- @Override
- public void setValue(String value) {
- super.setValue(value);
- mSpinner.setSelection(findIndexOfValue(getValue()));
- setSummary(getEntry());
- }
-
- public void setValueIndex(int index) {
- setValue(getEntryValues()[index].toString());
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder view) {
- super.onBindViewHolder(view);
- if (view.equals(mSpinner.getParent())) return;
- if (mSpinner.getParent() != null) {
- ((ViewGroup) mSpinner.getParent()).removeView(mSpinner);
- }
- final ViewGroup vg = (ViewGroup) view.itemView;
- vg.addView(mSpinner, 0);
- final ViewGroup.LayoutParams lp = mSpinner.getLayoutParams();
- lp.width = 0;
- mSpinner.setLayoutParams(lp);
- }
-}
diff --git a/src/com/android/settings/EncryptionInterstitial.java b/src/com/android/settings/EncryptionInterstitial.java
index 3aec03e..be75c87 100644
--- a/src/com/android/settings/EncryptionInterstitial.java
+++ b/src/com/android/settings/EncryptionInterstitial.java
@@ -26,10 +26,12 @@
import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
+import android.widget.Button;
import android.widget.RadioButton;
import android.widget.TextView;
@@ -39,9 +41,12 @@
import java.util.List;
public class EncryptionInterstitial extends SettingsActivity {
+ private final static String TAG = EncryptionInterstitial.class.getSimpleName();
protected static final String EXTRA_PASSWORD_QUALITY = "extra_password_quality";
+ protected static final String EXTRA_UNLOCK_METHOD_INTENT = "extra_unlock_method_intent";
public static final String EXTRA_REQUIRE_PASSWORD = "extra_require_password";
+ private static final int CHOOSE_LOCK_REQUEST = 100;
@Override
public Intent getIntent() {
@@ -56,7 +61,7 @@
}
public static Intent createStartIntent(Context ctx, int quality,
- boolean requirePasswordDefault) {
+ boolean requirePasswordDefault, Intent unlockMethodIntent) {
return new Intent(ctx, EncryptionInterstitial.class)
.putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, true)
.putExtra(EXTRA_PREFS_SET_BACK_TEXT, (String) null)
@@ -64,7 +69,8 @@
R.string.encryption_continue_button))
.putExtra(EXTRA_PASSWORD_QUALITY, quality)
.putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, R.string.encryption_interstitial_header)
- .putExtra(EXTRA_REQUIRE_PASSWORD, requirePasswordDefault);
+ .putExtra(EXTRA_REQUIRE_PASSWORD, requirePasswordDefault)
+ .putExtra(EXTRA_UNLOCK_METHOD_INTENT, unlockMethodIntent);
}
public static class EncryptionInterstitialFragment extends SettingsPreferenceFragment
@@ -75,6 +81,7 @@
private RadioButton mDontRequirePasswordToDecryptButton;
private TextView mEncryptionMessage;
private boolean mPasswordRequired;
+ private Intent mUnlockMethodIntent;
@Override
protected int getMetricsCategory() {
@@ -98,7 +105,9 @@
(TextView) view.findViewById(R.id.encryption_message);
boolean forFingerprint = getActivity().getIntent().getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
- int quality = getActivity().getIntent().getIntExtra(EXTRA_PASSWORD_QUALITY, 0);
+ Intent intent = getActivity().getIntent();
+ final int quality = intent.getIntExtra(EXTRA_PASSWORD_QUALITY, 0);
+ mUnlockMethodIntent = (Intent) intent.getParcelableExtra(EXTRA_UNLOCK_METHOD_INTENT);
final int msgId;
final int enableId;
final int disableId;
@@ -136,6 +145,35 @@
setRequirePasswordState(getActivity().getIntent().getBooleanExtra(
EXTRA_REQUIRE_PASSWORD, true));
+
+ Button nextButton = getNextButton();
+ if (nextButton != null) {
+ nextButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ startLockIntent();
+ }
+ });
+ }
+ }
+
+ protected void startLockIntent() {
+ if (mUnlockMethodIntent != null) {
+ mUnlockMethodIntent.putExtra(EXTRA_REQUIRE_PASSWORD, mPasswordRequired);
+ startActivityForResult(mUnlockMethodIntent, CHOOSE_LOCK_REQUEST);
+ } else {
+ Log.wtf(TAG, "no unlock intent to start");
+ finish();
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == CHOOSE_LOCK_REQUEST && resultCode != RESULT_CANCELED) {
+ getActivity().setResult(resultCode, data);
+ finish();
+ }
}
@Override
@@ -206,15 +244,6 @@
mPasswordRequired = required;
mRequirePasswordToDecryptButton.setChecked(required);
mDontRequirePasswordToDecryptButton.setChecked(!required);
-
- // Updates value returned by SettingsActivity.onActivityResult().
- SettingsActivity sa = (SettingsActivity)getActivity();
- Intent resultIntentData = sa.getResultIntentData();
- if (resultIntentData == null) {
- resultIntentData = new Intent();
- sa.setResultIntentData(resultIntentData);
- }
- resultIntentData.putExtra(EXTRA_REQUIRE_PASSWORD, mPasswordRequired);
}
@Override
diff --git a/src/com/android/settings/FallbackHome.java b/src/com/android/settings/FallbackHome.java
index f92f2b2..d3e6482 100644
--- a/src/com/android/settings/FallbackHome.java
+++ b/src/com/android/settings/FallbackHome.java
@@ -21,25 +21,57 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ResolveInfo;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.UserManager;
import android.util.Log;
+import java.util.Objects;
+
public class FallbackHome extends Activity {
private static final String TAG = "FallbackHome";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
+ maybeFinish();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ unregisterReceiver(mReceiver);
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- Log.d(TAG, "User unlocked; leaving to find real home");
- unregisterReceiver(this);
- finish();
+ maybeFinish();
+ }
+ };
+
+ private void maybeFinish() {
+ if (getSystemService(UserManager.class).isUserUnlocked()) {
+ final Intent homeIntent = new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_HOME);
+ final ResolveInfo homeInfo = getPackageManager().resolveActivity(homeIntent, 0);
+ if (Objects.equals(getPackageName(), homeInfo.activityInfo.packageName)) {
+ Log.d(TAG, "User unlocked but no home; let's hope someone enables one soon?");
+ mHandler.sendEmptyMessageDelayed(0, 500);
+ } else {
+ Log.d(TAG, "User unlocked and real home found; let's go!");
+ finish();
+ }
+ }
+ }
+
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ maybeFinish();
}
};
}
diff --git a/src/com/android/settings/InstrumentedFragment.java b/src/com/android/settings/InstrumentedFragment.java
index 80e1131..cc0014d 100644
--- a/src/com/android/settings/InstrumentedFragment.java
+++ b/src/com/android/settings/InstrumentedFragment.java
@@ -31,6 +31,8 @@
public static final int ACCESSIBILITY_TOGGLE_AUTOCLICK = UNDECLARED + 1;
public static final int SOUND = UNDECLARED + 2;
public static final int CONFIGURE_NOTIFICATION = UNDECLARED + 3;
+ public static final int CONFIGURE_WIFI = UNDECLARED + 4;
+ public static final int DISPLAY_SCREEN_ZOOM = UNDECLARED + 5;
/**
* Declare the view of this category.
diff --git a/src/com/android/settings/LocalePicker.java b/src/com/android/settings/LocalePicker.java
index 8ea99a1..950b79c 100644
--- a/src/com/android/settings/LocalePicker.java
+++ b/src/com/android/settings/LocalePicker.java
@@ -28,8 +28,8 @@
import java.util.Locale;
-public class LocalePicker extends com.android.internal.app.LocalePicker
- implements com.android.internal.app.LocalePicker.LocaleSelectionListener,
+public class LocalePicker extends com.android.internal.app.LocalePickerWithRegion
+ implements com.android.internal.app.LocalePickerWithRegion.LocaleSelectionListener,
DialogCreatable {
private static final String TAG = "LocalePicker";
@@ -69,7 +69,7 @@
showDialog(DLG_SHOW_GLOBAL_WARNING);
} else {
getActivity().onBackPressed();
- LocalePicker.updateLocale(locale);
+ com.android.internal.app.LocalePicker.updateLocale(locale);
}
}
@@ -97,7 +97,7 @@
public void run() {
removeDialog(dialogId);
getActivity().onBackPressed();
- LocalePicker.updateLocale(mTargetLocale);
+ com.android.internal.app.LocalePicker.updateLocale(mTargetLocale);
}
}
);
diff --git a/src/com/android/settings/PrivacySettings.java b/src/com/android/settings/PrivacySettings.java
index 2344a33..0735b11 100644
--- a/src/com/android/settings/PrivacySettings.java
+++ b/src/com/android/settings/PrivacySettings.java
@@ -291,10 +291,6 @@
nonVisibleKeys.add(CONFIGURE_ACCOUNT);
}
if (UserManager.get(context).hasUserRestriction(
- UserManager.DISALLOW_FACTORY_RESET)) {
- nonVisibleKeys.add(FACTORY_RESET);
- }
- if (UserManager.get(context).hasUserRestriction(
UserManager.DISALLOW_NETWORK_RESET)) {
nonVisibleKeys.add(NETWORK_RESET);
}
diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java
index 2f10bb5..7ed70c7 100644
--- a/src/com/android/settings/RadioInfo.java
+++ b/src/com/android/settings/RadioInfo.java
@@ -22,6 +22,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
+import android.graphics.Typeface;
import android.net.TrafficStats;
import android.net.Uri;
import android.os.AsyncResult;
@@ -30,11 +31,24 @@
import android.os.Message;
import android.os.SystemProperties;
import android.telephony.CellInfo;
+import android.telephony.CellInfoCdma;
+import android.telephony.CellInfoGsm;
+import android.telephony.CellInfoLte;
+import android.telephony.CellInfoWcdma;
+import android.telephony.CellIdentityCdma;
+import android.telephony.CellIdentityGsm;
+import android.telephony.CellIdentityLte;
+import android.telephony.CellIdentityWcdma;
import android.telephony.CellLocation;
+import android.telephony.CellSignalStrengthCdma;
+import android.telephony.CellSignalStrengthGsm;
+import android.telephony.CellSignalStrengthLte;
+import android.telephony.CellSignalStrengthWcdma;
import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.NeighboringCellInfo;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;
@@ -57,6 +71,7 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.PhoneStateIntentReceiver;
+import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.TelephonyProperties;
import java.io.IOException;
@@ -76,7 +91,6 @@
private static final int EVENT_QUERY_PREFERRED_TYPE_DONE = 1000;
private static final int EVENT_SET_PREFERRED_TYPE_DONE = 1001;
- private static final int EVENT_QUERY_NEIGHBORING_CIDS_DONE = 1002;
private static final int EVENT_QUERY_SMSC_DONE = 1005;
private static final int EVENT_UPDATE_SMSC_DONE = 1006;
@@ -112,8 +126,8 @@
private TextView sentSinceReceived;
private TextView sent;
private TextView received;
- private TextView mPingIpAddr;
- private TextView mPingHostname;
+ private TextView mPingHostnameV4;
+ private TextView mPingHostnameV6;
private TextView mHttpClientTest;
private TextView dnsCheckState;
private EditText smsc;
@@ -127,15 +141,21 @@
private Spinner preferredNetworkType;
private TelephonyManager mTelephonyManager;
+ private ImsManager mImsManager = null;
private Phone phone = null;
private PhoneStateIntentReceiver mPhoneStateReceiver;
- private String mPingIpAddrResult;
- private String mPingHostnameResult;
+ private String mPingHostnameResultV4;
+ private String mPingHostnameResultV6;
private String mHttpClientTestResult;
private boolean mMwiValue = false;
private boolean mCfiValue = false;
- private List<CellInfo> mCellInfoValue;
+
+ private List<CellInfo> mCellInfoResult = null;
+ private CellLocation mCellLocationResult = null;
+ private List<NeighboringCellInfo> mNeighboringCellResult = null;
+
+ private int mPreferredNetworkTypeResult;
private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
@@ -171,7 +191,8 @@
@Override
public void onCellInfoChanged(List<CellInfo> arrayCi) {
log("onCellInfoChanged: arrayCi=" + arrayCi);
- updateCellInfoTv(arrayCi);
+ mCellInfoResult = arrayCi;
+ updateCellInfo(mCellInfoResult);
}
@Override
@@ -181,7 +202,19 @@
}
};
+ private void updatePreferredNetworkType(int type) {
+ if (type >= mPreferredNetworkLabels.length || type < 0) {
+ log("EVENT_QUERY_PREFERRED_TYPE_DONE: unknown " +
+ "type=" + type);
+ type = mPreferredNetworkLabels.length - 1; //set to Unknown
+ }
+ mPreferredNetworkTypeResult = type;
+
+ preferredNetworkType.setSelection(mPreferredNetworkTypeResult, true);
+ }
+
private Handler mHandler = new Handler() {
+ @Override
public void handleMessage(Message msg) {
AsyncResult ar;
switch (msg.what) {
@@ -201,31 +234,17 @@
case EVENT_QUERY_PREFERRED_TYPE_DONE:
ar= (AsyncResult) msg.obj;
- if (ar.exception == null) {
- int type = ((int[])ar.result)[0];
- if (type >= mPreferredNetworkLabels.length) {
- log("EVENT_QUERY_PREFERRED_TYPE_DONE: unknown " +
- "type=" + type);
- type = mPreferredNetworkLabels.length - 1;
- }
- preferredNetworkType.setSelection(type, true);
+ if (ar.exception == null && ar.result != null) {
+ updatePreferredNetworkType(((int[])ar.result)[0]);
} else {
- preferredNetworkType.setSelection(mPreferredNetworkLabels.length - 1, true);
+ //In case of an exception, we will set this to unknown
+ updatePreferredNetworkType(mPreferredNetworkLabels.length-1);
}
break;
case EVENT_SET_PREFERRED_TYPE_DONE:
ar= (AsyncResult) msg.obj;
if (ar.exception != null) {
- phone.getPreferredNetworkType(
- obtainMessage(EVENT_QUERY_PREFERRED_TYPE_DONE));
- }
- break;
- case EVENT_QUERY_NEIGHBORING_CIDS_DONE:
- ar= (AsyncResult) msg.obj;
- if (ar.exception == null) {
- updateNeighboringCids((ArrayList<NeighboringCellInfo>)ar.result);
- } else {
- mNeighboringCids.setText("unknown");
+ log("Set preferred network type success.");
}
break;
case EVENT_QUERY_SMSC_DONE:
@@ -244,6 +263,7 @@
}
break;
default:
+ super.handleMessage(msg);
break;
}
@@ -256,9 +276,16 @@
setContentView(R.layout.radio_info);
+ log("Started onCreate");
+
mTelephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
phone = PhoneFactory.getDefaultPhone();
+ //TODO: Need to update this if the default phoneId changes?
+ // Better to have an instance per phone?
+ mImsManager = ImsManager.getInstance(getApplicationContext(),
+ SubscriptionManager.getDefaultVoicePhoneId());
+
mDeviceId= (TextView) findViewById(R.id.imei);
number = (TextView) findViewById(R.id.number);
callState = (TextView) findViewById(R.id.call);
@@ -273,6 +300,7 @@
mLocation = (TextView) findViewById(R.id.location);
mNeighboringCids = (TextView) findViewById(R.id.neighboring);
mCellInfo = (TextView) findViewById(R.id.cellinfo);
+ mCellInfo.setTypeface(Typeface.MONOSPACE);
mDcRtInfoTv = (TextView) findViewById(R.id.dcrtinfo);
resets = (TextView) findViewById(R.id.resets);
@@ -284,9 +312,8 @@
received = (TextView) findViewById(R.id.received);
smsc = (EditText) findViewById(R.id.smsc);
dnsCheckState = (TextView) findViewById(R.id.dnsCheckState);
-
- mPingIpAddr = (TextView) findViewById(R.id.pingIpAddr);
- mPingHostname = (TextView) findViewById(R.id.pingHostname);
+ mPingHostnameV4 = (TextView) findViewById(R.id.pingHostnameV4);
+ mPingHostnameV6 = (TextView) findViewById(R.id.pingHostnameV6);
mHttpClientTest = (TextView) findViewById(R.id.httpClientTest);
preferredNetworkType = (Spinner) findViewById(R.id.preferredNetworkType);
@@ -337,28 +364,26 @@
mPhoneStateReceiver.notifyServiceState(EVENT_SERVICE_STATE_CHANGED);
mPhoneStateReceiver.notifyPhoneCallState(EVENT_PHONE_STATE_CHANGED);
+ mPreferredNetworkTypeResult = mPreferredNetworkLabels.length - 1; //Unknown
+
+ //FIXME: Replace with TelephonyManager call
phone.getPreferredNetworkType(
mHandler.obtainMessage(EVENT_QUERY_PREFERRED_TYPE_DONE));
- phone.getNeighboringCids(
- mHandler.obtainMessage(EVENT_QUERY_NEIGHBORING_CIDS_DONE));
- CellLocation.requestLocationUpdate();
-
- // Get current cell info
- mCellInfoValue = mTelephonyManager.getAllCellInfo();
- log("onCreate: mCellInfoValue=" + mCellInfoValue);
+ restoreFromBundle(icicle);
}
@Override
protected void onResume() {
super.onResume();
+ log("Started onResume");
+
updatePhoneState();
updateSignalStrength();
updateMessageWaiting();
updateCallRedirect();
updateServiceState();
- updateLocation(mTelephonyManager.getCellLocation());
updateDataState();
updateDataStats();
updateDataStats2();
@@ -371,7 +396,13 @@
updateProperties();
updateDnsCheckState();
- log("onResume: register phone & data intents");
+ updateNeighboringCids(mNeighboringCellResult);
+ updateLocation(mCellLocationResult);
+ updateCellInfo(mCellInfoResult);
+
+ mPingHostnameV4.setText(mPingHostnameResultV4);
+ mPingHostnameV6.setText(mPingHostnameResultV6);
+ mHttpClientTest.setText(mHttpClientTestResult);
mPhoneStateReceiver.registerIntent();
mTelephonyManager.listen(mPhoneStateListener,
@@ -385,7 +416,7 @@
}
@Override
- public void onPause() {
+ protected void onPause() {
super.onPause();
log("onPause: unregister phone & data intents");
@@ -394,6 +425,30 @@
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
}
+ private void restoreFromBundle(Bundle b) {
+ if( b == null) {
+ return;
+ }
+
+ mPingHostnameResultV4 = b.getString("mPingHostnameResultV4","");
+ mPingHostnameResultV6 = b.getString("mPingHostnameResultV6","");
+ mHttpClientTestResult = b.getString("mHttpClientTestResult","");
+
+ mPingHostnameV4.setText(mPingHostnameResultV4);
+ mPingHostnameV6.setText(mPingHostnameResultV6);
+ mHttpClientTest.setText(mHttpClientTestResult);
+
+ mPreferredNetworkTypeResult = b.getInt("mPreferredNetworkTypeResult", 0);
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ outState.putString("mPingHostnameResultV4", mPingHostnameResultV4);
+ outState.putString("mPingHostnameResultV6", mPingHostnameResultV6);
+ outState.putString("mHttpClientTestResult", mHttpClientTestResult);
+ outState.putInt("mPreferredNetworkTypeResult", mPreferredNetworkTypeResult);
+ }
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, MENU_ITEM_SELECT_BAND, 0, R.string.radio_info_band_mode_label)
@@ -436,6 +491,7 @@
}
private boolean isRadioOn() {
+ //FIXME: Replace with a TelephonyManager call
return phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
}
@@ -447,11 +503,24 @@
}
private void updateCellInfoListRate() {
- cellInfoListRateButton.setText("CellInfoListRate " + mCellInfoListRateHandler.getRate());
- updateCellInfoTv(mTelephonyManager.getAllCellInfo());
+ int rate = mCellInfoListRateHandler.getRate();
+ String rateStr;
+ switch(rate) {
+ case Integer.MAX_VALUE:
+ rateStr = "Off";
+ break;
+ case 0:
+ rateStr = "Immediate";
+ break;
+ default:
+ rateStr = (new Integer(rate)).toString() + "ms";
+ break;
+ }
+ cellInfoListRateButton.setText("CellInfoListRate "+ rateStr);
}
private void updateDnsCheckState() {
+ //FIXME: Replace with a TelephonyManager call
dnsCheckState.setText(phone.isDnsCheckDisabled() ?
"0.0.0.0 allowed" :"0.0.0.0 not allowed");
}
@@ -521,7 +590,7 @@
}
- private final void updateNeighboringCids(ArrayList<NeighboringCellInfo> cids) {
+ private final void updateNeighboringCids(List<NeighboringCellInfo> cids) {
StringBuilder sb = new StringBuilder();
if (cids != null) {
@@ -538,22 +607,128 @@
mNeighboringCids.setText(sb.toString());
}
- private final void updateCellInfoTv(List<CellInfo> arrayCi) {
- mCellInfoValue = arrayCi;
- StringBuilder value = new StringBuilder();
- if (mCellInfoValue != null) {
- int index = 0;
- for (CellInfo ci : mCellInfoValue) {
- value.append('[');
- value.append(index);
- value.append("]=");
- value.append(ci.toString());
- if (++index < mCellInfoValue.size()) {
- value.append("\n");
+ private final String getCellInfoDisplayString(int i) {
+ return (i != Integer.MAX_VALUE) ? Integer.toString(i) : "";
+ }
+
+ private final String getCellInfoDisplayString(long i) {
+ return (i != Long.MAX_VALUE) ? Long.toString(i) : "";
+ }
+
+ private final String buildCdmaInfoString(CellInfoCdma ci) {
+ CellIdentityCdma cidCdma = ci.getCellIdentity();
+ CellSignalStrengthCdma ssCdma = ci.getCellSignalStrength();
+
+ return String.format("%-3.3s %-5.5s %-5.5s %-5.5s %-6.6s %-6.6s %-6.6s %-6.6s %-5.5s",
+ ci.isRegistered() ? "S " : " ",
+ getCellInfoDisplayString(cidCdma.getSystemId()),
+ getCellInfoDisplayString(cidCdma.getNetworkId()),
+ getCellInfoDisplayString(cidCdma.getBasestationId()),
+ getCellInfoDisplayString(ssCdma.getCdmaDbm()),
+ getCellInfoDisplayString(ssCdma.getCdmaEcio()),
+ getCellInfoDisplayString(ssCdma.getEvdoDbm()),
+ getCellInfoDisplayString(ssCdma.getEvdoEcio()),
+ getCellInfoDisplayString(ssCdma.getEvdoSnr()));
+ }
+
+ private final String buildGsmInfoString(CellInfoGsm ci) {
+ CellIdentityGsm cidGsm = ci.getCellIdentity();
+ CellSignalStrengthGsm ssGsm = ci.getCellSignalStrength();
+
+ return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-4.4s %-4.4s\n",
+ ci.isRegistered() ? "S " : " ",
+ getCellInfoDisplayString(cidGsm.getMcc()),
+ getCellInfoDisplayString(cidGsm.getMnc()),
+ getCellInfoDisplayString(cidGsm.getLac()),
+ getCellInfoDisplayString(cidGsm.getCid()),
+ // TODO: Add BSIC support once integrated
+ // getCellInfoDisplayString(cidGsm.getBsic()),
+ " ",
+ getCellInfoDisplayString(ssGsm.getDbm()));
+ }
+
+ private final String buildLteInfoString(CellInfoLte ci) {
+ CellIdentityLte cidLte = ci.getCellIdentity();
+ CellSignalStrengthLte ssLte = ci.getCellSignalStrength();
+
+ return String.format(
+ "%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s %-4.4s %-4.4s %-2.2s\n",
+ ci.isRegistered() ? "S " : " ",
+ getCellInfoDisplayString(cidLte.getMcc()),
+ getCellInfoDisplayString(cidLte.getMnc()),
+ getCellInfoDisplayString(cidLte.getTac()),
+ getCellInfoDisplayString(cidLte.getCi()),
+ getCellInfoDisplayString(cidLte.getPci()),
+ getCellInfoDisplayString(ssLte.getDbm()),
+ getCellInfoDisplayString(ssLte.getRsrq()),
+ getCellInfoDisplayString(ssLte.getTimingAdvance()));
+ }
+
+ private final String buildWcdmaInfoString(CellInfoWcdma ci) {
+ CellIdentityWcdma cidWcdma = ci.getCellIdentity();
+ CellSignalStrengthWcdma ssWcdma = ci.getCellSignalStrength();
+
+ return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-5.5s %-4.4s\n",
+ ci.isRegistered() ? "S " : " ",
+ getCellInfoDisplayString(cidWcdma.getMcc()),
+ getCellInfoDisplayString(cidWcdma.getMnc()),
+ getCellInfoDisplayString(cidWcdma.getLac()),
+ getCellInfoDisplayString(cidWcdma.getCid()),
+ getCellInfoDisplayString(cidWcdma.getPsc()),
+ getCellInfoDisplayString(ssWcdma.getDbm()));
+ }
+
+ private final String buildCellInfoString(List<CellInfo> arrayCi) {
+ String value = new String();
+ StringBuilder cdmaCells = new StringBuilder(),
+ gsmCells = new StringBuilder(),
+ lteCells = new StringBuilder(),
+ wcdmaCells = new StringBuilder();
+
+ if (arrayCi != null) {
+ for (CellInfo ci : arrayCi) {
+
+ if (ci instanceof CellInfoLte) {
+ lteCells.append(buildLteInfoString((CellInfoLte) ci));
+ } else if (ci instanceof CellInfoWcdma) {
+ wcdmaCells.append(buildWcdmaInfoString((CellInfoWcdma) ci));
+ } else if (ci instanceof CellInfoGsm) {
+ gsmCells.append(buildGsmInfoString((CellInfoGsm) ci));
+ } else if (ci instanceof CellInfoCdma) {
+ cdmaCells.append(buildCdmaInfoString((CellInfoCdma) ci));
}
}
+ if (lteCells.length() != 0) {
+ value += String.format(
+ "LTE\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s %-4.4s %-4.4s %-2.2s\n",
+ "SRV", "MCC", "MNC", "TAC", "CID", "PCI", "RSRP", "RSRQ", "TA");
+ value += lteCells.toString();
+ }
+ if (wcdmaCells.length() != 0) {
+ value += String.format("WCDMA\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-5.5s %-4.4s\n",
+ "SRV", "MCC", "MNC", "LAC", "CID", "PSC", "RSCP");
+ value += wcdmaCells.toString();
+ }
+ if (gsmCells.length() != 0) {
+ value += String.format("GSM\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-4.4s %-4.4s\n",
+ "SRV", "MCC", "MNC", "LAC", "CID", "BSIC", "RSSI");
+ value += gsmCells.toString();
+ }
+ if (cdmaCells.length() != 0) {
+ value += String.format(
+ "CDMA/EVDO\n%-3.3s %-5.5s %-5.5s %-5.5s %-6.6s %-6.6s %-6.6s %-6.6s %-5.5s\n",
+ "SRV", "SID", "NID", "BSID", "C-RSSI", "C-ECIO", "E-RSSI", "E-ECIO", "E-SNR");
+ value += cdmaCells.toString();
+ }
+ } else {
+ value ="unknown";
}
- mCellInfo.setText(value.toString());
+
+ return value.toString();
+ }
+
+ private final void updateCellInfo(List<CellInfo> arrayCi) {
+ mCellInfo.setText(buildCellInfoString(arrayCi));
}
private final void updateDcRtInfoTv(DataConnectionRealTimeInfo dcRtInfo) {
@@ -664,7 +839,7 @@
if (s == null) s = r.getString(R.string.radioInfo_unknown);
mDeviceId.setText(s);
-
+ //FIXME: Replace with a TelephonyManager call
s = phone.getLine1Number();
if (s == null) s = r.getString(R.string.radioInfo_unknown);
number.setText(s);
@@ -705,45 +880,34 @@
}
/**
- * Ping a IP address.
- */
- private final void pingIpAddr() {
- try {
- // This is hardcoded IP addr. This is for testing purposes.
- // We would need to get rid of this before release.
- String ipAddress = "74.125.47.104";
- Process p = Runtime.getRuntime().exec("ping -c 1 " + ipAddress);
- int status = p.waitFor();
- if (status == 0) {
- mPingIpAddrResult = "Pass";
- } else {
- mPingIpAddrResult = "Fail: IP addr not reachable";
- }
- } catch (IOException e) {
- mPingIpAddrResult = "Fail: IOException";
- } catch (InterruptedException e) {
- mPingIpAddrResult = "Fail: InterruptedException";
- }
- }
-
- /**
* Ping a host name
*/
private final void pingHostname() {
try {
- Process p = Runtime.getRuntime().exec("ping -c 1 www.google.com");
- int status = p.waitFor();
- if (status == 0) {
- mPingHostnameResult = "Pass";
- } else {
- mPingHostnameResult = "Fail: Host unreachable";
+ try {
+ Process p4 = Runtime.getRuntime().exec("ping -c 1 www.google.com");
+ int status4 = p4.waitFor();
+ if (status4 == 0) {
+ mPingHostnameResultV4 = "Pass";
+ } else {
+ mPingHostnameResultV4 = String.format("Fail(%d)", status4);
+ }
+ } catch (IOException e) {
+ mPingHostnameResultV4 = "Fail: IOException";
}
- } catch (UnknownHostException e) {
- mPingHostnameResult = "Fail: Unknown Host";
- } catch (IOException e) {
- mPingHostnameResult= "Fail: IOException";
+ try {
+ Process p6 = Runtime.getRuntime().exec("ping6 -c 1 www.google.com");
+ int status6 = p6.waitFor();
+ if (status6 == 0) {
+ mPingHostnameResultV6 = "Pass";
+ } else {
+ mPingHostnameResultV6 = String.format("Fail(%d)", status6);
+ }
+ } catch (IOException e) {
+ mPingHostnameResultV6 = "Fail: IOException";
+ }
} catch (InterruptedException e) {
- mPingHostnameResult = "Fail: InterruptedException";
+ mPingHostnameResultV4 = mPingHostnameResultV6 = "Fail: InterruptedException";
}
}
@@ -771,41 +935,60 @@
}
private void refreshSmsc() {
+ //FIXME: Replace with a TelephonyManager call
phone.getSmscAddress(mHandler.obtainMessage(EVENT_QUERY_SMSC_DONE));
}
+ private final void updateAllCellInfo() {
+
+ mCellInfo.setText("");
+ mNeighboringCids.setText("");
+ mLocation.setText("");
+
+ final Runnable updateAllCellInfoResults = new Runnable() {
+ public void run() {
+ updateNeighboringCids(mNeighboringCellResult);
+ updateLocation(mCellLocationResult);
+ updateCellInfo(mCellInfoResult);
+ }
+ };
+
+ Thread locThread = new Thread() {
+ @Override
+ public void run() {
+ mCellInfoResult = mTelephonyManager.getAllCellInfo();
+ mCellLocationResult = mTelephonyManager.getCellLocation();
+ mNeighboringCellResult = mTelephonyManager.getNeighboringCellInfo();
+
+ mHandler.post(updateAllCellInfoResults);
+ }
+ };
+ locThread.start();
+ }
+
private final void updatePingState() {
- final Handler handler = new Handler();
// Set all to unknown since the threads will take a few secs to update.
- mPingIpAddrResult = getResources().getString(R.string.radioInfo_unknown);
- mPingHostnameResult = getResources().getString(R.string.radioInfo_unknown);
+ mPingHostnameResultV4 = getResources().getString(R.string.radioInfo_unknown);
+ mPingHostnameResultV6 = getResources().getString(R.string.radioInfo_unknown);
mHttpClientTestResult = getResources().getString(R.string.radioInfo_unknown);
- mPingIpAddr.setText(mPingIpAddrResult);
- mPingHostname.setText(mPingHostnameResult);
+ mPingHostnameV4.setText(mPingHostnameResultV4);
+ mPingHostnameV6.setText(mPingHostnameResultV6);
mHttpClientTest.setText(mHttpClientTestResult);
final Runnable updatePingResults = new Runnable() {
public void run() {
- mPingIpAddr.setText(mPingIpAddrResult);
- mPingHostname.setText(mPingHostnameResult);
+ mPingHostnameV4.setText(mPingHostnameResultV4);
+ mPingHostnameV6.setText(mPingHostnameResultV6);
mHttpClientTest.setText(mHttpClientTestResult);
}
};
- Thread ipAddr = new Thread() {
- @Override
- public void run() {
- pingIpAddr();
- handler.post(updatePingResults);
- }
- };
- ipAddr.start();
Thread hostname = new Thread() {
@Override
public void run() {
pingHostname();
- handler.post(updatePingResults);
+ mHandler.post(updatePingResults);
}
};
hostname.start();
@@ -814,7 +997,7 @@
@Override
public void run() {
httpClientTest();
- handler.post(updatePingResults);
+ mHandler.post(updatePingResults);
}
};
httpClient.start();
@@ -910,6 +1093,7 @@
private MenuItem.OnMenuItemClickListener mGetPdpList = new MenuItem.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
+ //FIXME: Replace with a TelephonyManager call
phone.getDataCallList(null);
return true;
}
@@ -929,9 +1113,11 @@
int state = mTelephonyManager.getDataState();
switch (state) {
case TelephonyManager.DATA_CONNECTED:
+ //FIXME: Replace with a TelephonyManager call
phone.setDataEnabled(false);
break;
case TelephonyManager.DATA_DISCONNECTED:
+ //FIXME: Replace with a TelephonyManager call
phone.setDataEnabled(true);
break;
default:
@@ -945,12 +1131,13 @@
OnClickListener mPowerButtonHandler = new OnClickListener() {
public void onClick(View v) {
//log("toggle radio power: currently " + (isRadioOn()?"on":"off"));
+ //FIXME: Replace with a TelephonyManager call
phone.setRadioPower(!isRadioOn());
}
};
class CellInfoListRateHandler implements OnClickListener {
- int rates[] = {Integer.MAX_VALUE, 0, 1000};
+ int rates[] = {Integer.MAX_VALUE, 0, 5000};
int index = 0;
public int getRate() {
@@ -960,11 +1147,13 @@
@Override
public void onClick(View v) {
index += 1;
- if (index >= rates.length) {
- index = 0;
- }
+ index %= rates.length;
+
+ // FIXME: Replace with a TelephonyManager call
phone.setCellInfoListRate(rates[index]);
updateCellInfoListRate();
+
+ updateAllCellInfo();
}
}
CellInfoListRateHandler mCellInfoListRateHandler = new CellInfoListRateHandler();
@@ -1020,12 +1209,12 @@
(isImsVoLteProvisioned() ? "on":"off")));
final boolean newValue = !isImsVoLteProvisioned();
if (phone != null) {
- final ImsManager imsManager = ImsManager.getInstance(phone.getContext(), phone.getSubId());
- if (imsManager != null) {
+ //TODO: Why does this have to be called within the phone's context?
+ if (mImsManager != null) {
QueuedWork.singleThreadExecutor().submit(new Runnable() {
public void run() {
try {
- imsManager.getConfigInterface().setProvisionedValue(
+ mImsManager.getConfigInterface().setProvisionedValue(
ImsConfig.ConfigConstants.VLT_SETTING_ENABLED,
newValue? 1 : 0);
} catch (ImsException e) {
@@ -1041,8 +1230,10 @@
private boolean isImsVoLteProvisioned() {
if (phone != null) {
- ImsManager imsManager = ImsManager.getInstance(phone.getContext(), phone.getSubId());
- return imsManager.isVolteProvisionedOnDevice(phone.getContext());
+ //TODO: Why does this have to be called within the phone's context?
+ if(mImsManager != null ) {
+ return mImsManager.isVolteProvisionedOnDevice(phone.getContext());
+ }
}
return false;
}
@@ -1090,6 +1281,7 @@
OnClickListener mDnsCheckButtonHandler = new OnClickListener() {
public void onClick(View v) {
+ //FIXME: Replace with a TelephonyManager call
phone.disableDnsCheck(!phone.isDnsCheckDisabled());
updateDnsCheckState();
}
@@ -1128,12 +1320,15 @@
}
};
- AdapterView.OnItemSelectedListener
- mPreferredNetworkHandler = new AdapterView.OnItemSelectedListener() {
+ AdapterView.OnItemSelectedListener mPreferredNetworkHandler =
+ new AdapterView.OnItemSelectedListener() {
+
public void onItemSelected(AdapterView parent, View v, int pos, long id) {
- Message msg = mHandler.obtainMessage(EVENT_SET_PREFERRED_TYPE_DONE);
- if (pos>=0 && pos<=(mPreferredNetworkLabels.length - 2)) {
- phone.setPreferredNetworkType(pos, msg);
+ if (mPreferredNetworkTypeResult != pos && pos >= 0
+ && pos <= mPreferredNetworkLabels.length - 2) {
+ mPreferredNetworkTypeResult = pos;
+ Message msg = mHandler.obtainMessage(EVENT_SET_PREFERRED_TYPE_DONE);
+ phone.setPreferredNetworkType(mPreferredNetworkTypeResult, msg);
}
}
@@ -1149,11 +1344,21 @@
"CDMA auto (PRL)",
"CDMA only",
"EvDo only",
- "GSM/CDMA auto (PRL)",
+ "Global auto (PRL)",
"LTE/CDMA auto (PRL)",
- "LTE/GSM auto (PRL)",
- "LTE/GSM/CDMA auto (PRL)",
+ "LTE/UMTS auto (PRL)",
+ "LTE/CDMA/UMTS auto (PRL)",
"LTE only",
+ "LTE/WCDMA",
+ "TD-SCDMA only",
+ "TD-SCDMA/WCDMA",
+ "LTE/TD-SCDMA",
+ "TD-SCDMA/GSM",
+ "TD-SCDMA/UMTS",
+ "LTE/TD-SCDMA/WCDMA",
+ "LTE/TD-SCDMA/UMTS",
+ "TD-SCDMA/CDMA/UMTS",
+ "Global/TD-SCDMA",
"Unknown"};
private void log(String s) {
diff --git a/src/com/android/settings/ResetNetworkConfirm.java b/src/com/android/settings/ResetNetworkConfirm.java
index 9050448..4615a99 100644
--- a/src/com/android/settings/ResetNetworkConfirm.java
+++ b/src/com/android/settings/ResetNetworkConfirm.java
@@ -31,6 +31,7 @@
import android.widget.Button;
import android.widget.Toast;
+import com.android.ims.ImsManager;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.telephony.PhoneConstants;
@@ -94,6 +95,8 @@
btManager.getAdapter().factoryReset();
}
+ ImsManager.factoryReset(context);
+
Toast.makeText(context, R.string.reset_network_complete_toast, Toast.LENGTH_SHORT)
.show();
}
diff --git a/src/com/android/settings/RestrictedPreference.java b/src/com/android/settings/RestrictedPreference.java
new file mode 100644
index 0000000..7903f93
--- /dev/null
+++ b/src/com/android/settings/RestrictedPreference.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015 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;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.UserHandle;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.util.AttributeSet;
+
+/**
+ * Preference class that supports being disabled by a user restriction
+ * set by a device admin.
+ */
+public class RestrictedPreference extends Preference {
+ RestrictedPreferenceHelper mHelper;
+
+ public RestrictedPreference(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mHelper = new RestrictedPreferenceHelper(context, this, attrs);
+ }
+
+ public RestrictedPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public RestrictedPreference(Context context, AttributeSet attrs) {
+ this(context, attrs, TypedArrayUtils.getAttr(context, R.attr.preferenceStyle,
+ android.R.attr.preferenceStyle));
+ }
+
+ public RestrictedPreference(Context context) {
+ this(context, null);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ mHelper.onBindViewHolder(holder);
+ }
+
+ @Override
+ public void performClick() {
+ if (!mHelper.performClick()) {
+ super.performClick();
+ }
+ }
+
+ @Override
+ protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
+ mHelper.onAttachedToHierarchy();
+ super.onAttachedToHierarchy(preferenceManager);
+ }
+
+ public void checkRestrictionAndSetDisabled(String userRestriction) {
+ mHelper.checkRestrictionAndSetDisabled(userRestriction, UserHandle.myUserId());
+ }
+
+ public void checkRestrictionAndSetDisabled(String userRestriction, int userId) {
+ mHelper.checkRestrictionAndSetDisabled(userRestriction, userId);
+ }
+
+ public void setDisabledByAdmin(boolean disabled) {
+ mHelper.setDisabledByAdmin(disabled, null, UserHandle.USER_NULL);
+ }
+
+ public void setDisabledByAdmin(boolean disabled, ComponentName admin, int userId) {
+ if (mHelper.setDisabledByAdmin(disabled, admin, userId)) {
+ notifyChanged();
+ }
+ }
+
+ public boolean isDisabledByAdmin() {
+ return mHelper.isDisabledByAdmin();
+ }
+}
diff --git a/src/com/android/settings/RestrictedPreferenceHelper.java b/src/com/android/settings/RestrictedPreferenceHelper.java
new file mode 100644
index 0000000..0918887
--- /dev/null
+++ b/src/com/android/settings/RestrictedPreferenceHelper.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2015 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;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.View;
+import android.widget.TextView;
+
+/**
+ * Helper class for managing settings preferences that can be disabled
+ * by device admins via user restrictions.
+ *
+ **/
+public class RestrictedPreferenceHelper {
+ private final Context mContext;
+ private final Preference mPreference;
+ private final Drawable mRestrictedPadlock;
+ private final int mRestrictedPadlockPadding;
+ private final DevicePolicyManager mDevicePolicyManager;
+
+ private boolean mDisabledByAdmin;
+ private ComponentName mEnforcedAdmin;
+ private int mUserId = UserHandle.USER_NULL;
+ private String mAttrUserRestriction = null;
+
+ RestrictedPreferenceHelper(Context context, Preference preference,
+ AttributeSet attrs) {
+ mContext = context;
+ mPreference = preference;
+
+ mRestrictedPadlock = mContext.getDrawable(R.drawable.ic_settings_lock_outline);
+ final int iconSize = mContext.getResources().getDimensionPixelSize(
+ R.dimen.restricted_lock_icon_size);
+ mRestrictedPadlock.setBounds(0, 0, iconSize, iconSize);
+ mRestrictedPadlockPadding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.restricted_lock_icon_padding);
+
+ mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+
+ mAttrUserRestriction = attrs.getAttributeValue(
+ R.styleable.RestrictedPreference_userRestriction);
+ final TypedArray attributes = context.obtainStyledAttributes(attrs,
+ R.styleable.RestrictedPreference);
+ final TypedValue userRestriction =
+ attributes.peekValue(R.styleable.RestrictedPreference_userRestriction);
+ CharSequence data = null;
+ if (userRestriction != null && userRestriction.type == TypedValue.TYPE_STRING) {
+ if (userRestriction.resourceId != 0) {
+ data = context.getText(userRestriction.resourceId);
+ } else {
+ data = userRestriction.string;
+ }
+ }
+ mAttrUserRestriction = data == null ? null : data.toString();
+ }
+
+ /**
+ * Modify PreferenceViewHolder to add padlock if restriction is disabled.
+ */
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ final TextView titleView = (TextView) holder.findViewById(android.R.id.title);
+ if (titleView != null) {
+ if (mDisabledByAdmin) {
+ titleView.setCompoundDrawablesRelative(null, null, mRestrictedPadlock, null);
+ titleView.setCompoundDrawablePadding(mRestrictedPadlockPadding);
+ holder.itemView.setEnabled(true);
+ } else {
+ titleView.setCompoundDrawablesRelative(null, null, null, null);
+ }
+ }
+ }
+
+ /**
+ * Check if the preference is disabled if so handle the click by informing the user.
+ *
+ * @return true if the method handled the click.
+ */
+ public boolean performClick() {
+ if (mDisabledByAdmin) {
+ Intent intent = new Intent(mContext, ShowAdminSupportDetailsDialog.class);
+ if (mEnforcedAdmin != null) {
+ intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mEnforcedAdmin);
+ }
+ if (mUserId != UserHandle.USER_NULL) {
+ intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+ }
+ mContext.startActivity(intent);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Disable / enable if we have been passed the restriction in the xml.
+ */
+ protected void onAttachedToHierarchy() {
+ if (mAttrUserRestriction != null) {
+ checkRestrictionAndSetDisabled(mAttrUserRestriction, UserHandle.myUserId());
+ }
+ }
+
+ /**
+ * Set the user restriction that is used to disable this preference.
+ *
+ * @param userRestriction constant from {@link android.os.UserManager}
+ * @param userId user to check the restriction for.
+ */
+ public void checkRestrictionAndSetDisabled(String userRestriction, int userId) {
+ ComponentName deviceOwner = mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser();
+ int deviceOwnerUserId = mDevicePolicyManager.getDeviceOwnerUserId();
+ boolean enforcedByDeviceOwner = false;
+ if (deviceOwner != null && deviceOwnerUserId != UserHandle.USER_NULL) {
+ enforcedByDeviceOwner = isEnforcedByAdmin(
+ deviceOwner, userRestriction, deviceOwnerUserId);
+ }
+
+ ComponentName profileOwner = mDevicePolicyManager.getProfileOwnerAsUser(userId);
+ boolean enforcedByProfileOwner = false;
+ if (profileOwner != null && userId != UserHandle.USER_NULL) {
+ enforcedByProfileOwner = isEnforcedByAdmin(
+ profileOwner, userRestriction, userId);
+ }
+
+ if (!enforcedByDeviceOwner && !enforcedByProfileOwner) {
+ setDisabledByAdmin(false, null, UserHandle.USER_NULL);
+ return;
+ }
+
+ if (enforcedByDeviceOwner && enforcedByProfileOwner) {
+ setDisabledByAdmin(true, null, UserHandle.USER_NULL);
+ } else if (enforcedByDeviceOwner) {
+ setDisabledByAdmin(true, deviceOwner, deviceOwnerUserId);
+ } else {
+ setDisabledByAdmin(true, profileOwner, userId);
+ }
+ }
+
+ private boolean isEnforcedByAdmin(ComponentName admin, String userRestriction, int userId) {
+ Bundle enforcedRestrictions = mDevicePolicyManager.getUserRestrictions(admin, userId);
+ if (enforcedRestrictions != null
+ && enforcedRestrictions.getBoolean(userRestriction, false)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Disable this preference.
+ *
+ * @param disabled true if preference should be disabled.
+ * @param admin Device admin that disabled the preference.
+ * @param userId userId the device admin is installed for.
+ * @return true if the disabled state was changed.
+ */
+ public boolean setDisabledByAdmin(boolean disabled, ComponentName admin, int userId) {
+ if (mDisabledByAdmin != disabled) {
+ mDisabledByAdmin = disabled;
+ mEnforcedAdmin = admin;
+ mUserId = userId;
+ mPreference.setEnabled(!disabled);
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isDisabledByAdmin() {
+ return mDisabledByAdmin;
+ }
+}
diff --git a/src/com/android/settings/RestrictedSwitchPreference.java b/src/com/android/settings/RestrictedSwitchPreference.java
new file mode 100644
index 0000000..526bd42
--- /dev/null
+++ b/src/com/android/settings/RestrictedSwitchPreference.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015 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;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.UserHandle;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.support.v7.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.support.v14.preference.SwitchPreference;
+import android.util.AttributeSet;
+
+/**
+ * Version of SwitchPreference that can be disabled by a device admin
+ * using a user restriction.
+ */
+public class RestrictedSwitchPreference extends SwitchPreference {
+ RestrictedPreferenceHelper mHelper;
+
+ public RestrictedSwitchPreference(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mHelper = new RestrictedPreferenceHelper(context, this, attrs);
+ }
+
+ public RestrictedSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public RestrictedSwitchPreference(Context context, AttributeSet attrs) {
+ this(context, attrs, TypedArrayUtils.getAttr(context, R.attr.switchPreferenceStyle,
+ android.R.attr.switchPreferenceStyle));
+ }
+
+ public RestrictedSwitchPreference(Context context) {
+ this(context, null);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ mHelper.onBindViewHolder(holder);
+ }
+
+ @Override
+ public void performClick() {
+ if (!mHelper.performClick()) {
+ super.performClick();
+ }
+ }
+
+ @Override
+ protected void onAttachedToHierarchy(PreferenceManager preferenceManager) {
+ mHelper.onAttachedToHierarchy();
+ super.onAttachedToHierarchy(preferenceManager);
+ }
+
+ public void checkRestrictionAndSetDisabled(String userRestriction) {
+ mHelper.checkRestrictionAndSetDisabled(userRestriction, UserHandle.myUserId());
+ }
+
+ public void checkRestrictionAndSetDisabled(String userRestriction, int userId) {
+ mHelper.checkRestrictionAndSetDisabled(userRestriction, userId);
+ }
+
+ public void setDisabledByAdmin(boolean disabled) {
+ mHelper.setDisabledByAdmin(disabled, null, UserHandle.USER_NULL);
+ }
+
+ public void setDisabledByAdmin(boolean disabled, ComponentName admin, int userId) {
+ if (mHelper.setDisabledByAdmin(disabled, admin, userId)) {
+ notifyChanged();
+ }
+ }
+
+ public boolean isDisabledByAdmin() {
+ return mHelper.isDisabledByAdmin();
+ }
+}
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 838fcf3..fbe0f1c 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -129,7 +129,7 @@
private KeyStore mKeyStore;
private Preference mResetCredentials;
- private SwitchPreference mToggleAppInstallation;
+ private RestrictedSwitchPreference mToggleAppInstallation;
private DialogInterface mWarnInstallApps;
private SwitchPreference mPowerButtonInstantlyLocks;
@@ -313,15 +313,19 @@
// Application install
PreferenceGroup deviceAdminCategory = (PreferenceGroup)
root.findPreference(KEY_DEVICE_ADMIN_CATEGORY);
- mToggleAppInstallation = (SwitchPreference) findPreference(
+ mToggleAppInstallation = (RestrictedSwitchPreference) findPreference(
KEY_TOGGLE_INSTALL_APPLICATIONS);
mToggleAppInstallation.setChecked(isNonMarketAppsAllowed());
// Side loading of apps.
// Disable for restricted profiles. For others, check if policy disallows it.
mToggleAppInstallation.setEnabled(!um.getUserInfo(MY_USER_ID).isRestricted());
- if (um.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)
- || um.hasUserRestriction(UserManager.DISALLOW_INSTALL_APPS)) {
- mToggleAppInstallation.setEnabled(false);
+ if (mToggleAppInstallation.isEnabled()) {
+ mToggleAppInstallation.checkRestrictionAndSetDisabled(
+ UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
+ if (!mToggleAppInstallation.isDisabledByAdmin()) {
+ mToggleAppInstallation.checkRestrictionAndSetDisabled(
+ UserManager.DISALLOW_INSTALL_APPS);
+ }
}
// Advanced Security features
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 4380d1e..149ef45 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -61,6 +61,7 @@
return super.isValidFragment(className);
}
}
+ public static class BackgroundCheckSummaryActivity extends SettingsActivity { /* empty */ }
public static class StorageUseActivity extends SettingsActivity { /* empty */ }
public static class DevelopmentSettingsActivity extends SettingsActivity { /* empty */ }
public static class AccessibilitySettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 809a740..94379b3 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -32,6 +32,7 @@
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.nfc.NfcAdapter;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
@@ -374,7 +375,7 @@
if (pref.getFragment().equals(WallpaperTypeSettings.class.getName())) {
title = getString(R.string.wallpaper_settings_fragment_title);
}
- startPreferencePanel(pref.getFragment(), pref.getExtras(), 0, title,
+ startPreferencePanel(pref.getFragment(), pref.getExtras(), -1, title,
null, 0);
return true;
}
@@ -453,6 +454,7 @@
@Override
protected void onCreate(Bundle savedState) {
super.onCreate(savedState);
+ long startTime = System.currentTimeMillis();
// Should happen before any call to getIntent()
getMetaData();
@@ -506,7 +508,15 @@
if (mIsShowingDashboard) {
// Run the Index update only if we have some space
if (!Utils.isLowStorage(this)) {
- Index.getInstance(getApplicationContext()).update();
+ long indexStartTime = System.currentTimeMillis();
+ AsyncTask.execute(new Runnable() {
+ @Override
+ public void run() {
+ Index.getInstance(getApplicationContext()).update();
+ }
+ });
+ if (DEBUG_TIMING) Log.d(LOG_TAG, "Index.update() took "
+ + (System.currentTimeMillis() - indexStartTime) + " ms");
} else {
Log.w(LOG_TAG, "Cannot update the Indexer as we are running low on storage space!");
}
@@ -621,6 +631,8 @@
}
mHomeActivitiesCount = getHomeActivitiesCount();
+ if (DEBUG_TIMING) Log.d(LOG_TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
+ + " ms");
}
private int getHomeActivitiesCount() {
@@ -725,9 +737,6 @@
@Override
protected void onResume() {
super.onResume();
- if (mIsShowingDashboard) {
- MetricsLogger.visible(this, MetricsLogger.MAIN_SETTINGS);
- }
mDevelopmentPreferencesListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
@@ -751,9 +760,6 @@
@Override
protected void onPause() {
super.onPause();
- if (mIsShowingDashboard) {
- MetricsLogger.hidden(this, MetricsLogger.MAIN_SETTINGS);
- }
unregisterReceiver(mBatteryInfoReceiver);
mDynamicIndexableContentMonitor.unregister();
}
@@ -955,6 +961,18 @@
}
private void updateTilesList() {
+ // Generally the items that are will be changing from these updates will
+ // not be in the top list of tiles, so run it in the background and the
+ // SettingsDrawerActivity will pick up on the updates automatically.
+ AsyncTask.execute(new Runnable() {
+ @Override
+ public void run() {
+ doUpdateTilesList();
+ }
+ });
+ }
+
+ private void doUpdateTilesList() {
PackageManager pm = getPackageManager();
final UserManager um = UserManager.get(this);
final boolean isAdmin = um.isAdminUser();
@@ -1009,7 +1027,7 @@
if (UserHandle.MU_ENABLED && !isAdmin) {
// When on restricted users, disable all extra categories (but only the settings ones).
- List<DashboardCategory> categories = getDashboardCategories(true);
+ List<DashboardCategory> categories = getDashboardCategories();
for (DashboardCategory category : categories) {
for (DashboardTile tile : category.tiles) {
ComponentName component = tile.intent.getComponent();
@@ -1020,8 +1038,6 @@
}
}
}
-
- updateDrawer();
}
private void setTileEnabled(ComponentName component, boolean enabled, boolean isAdmin,
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index 34c773a..f79def9 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -27,8 +27,11 @@
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceGroupAdapter;
import android.support.v7.preference.PreferenceScreen;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
@@ -38,7 +41,6 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
-
import com.android.settings.applications.LayoutPreference;
import com.android.settings.widget.FloatingActionButton;
@@ -50,7 +52,7 @@
public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceFragment
implements DialogCreatable {
- private static final String TAG = "SettingsPreferenceFragment";
+ private static final String TAG = "SettingsPreference";
private static final int DELAY_HIGHLIGHT_DURATION_MILLIS = 600;
@@ -65,7 +67,6 @@
private String mPreferenceKey;
private boolean mPreferenceHighlighted = false;
- private Drawable mHighlightDrawable;
private RecyclerView.Adapter mCurrentRootAdapter;
private boolean mIsDataSetObserverRegistered = false;
@@ -85,6 +86,8 @@
private LayoutPreference mFooter;
private View mEmptyView;
+ private LinearLayoutManager mLayoutManager;
+ private HighlightablePreferenceGroupAdapter mAdapter;
@Override
public void onCreate(Bundle icicle) {
@@ -216,13 +219,6 @@
updateEmptyView();
}
- private Drawable getHighlightDrawable() {
- if (mHighlightDrawable == null) {
- mHighlightDrawable = getActivity().getDrawable(R.drawable.preference_highlight);
- }
- return mHighlightDrawable;
- }
-
public LayoutPreference getHeaderView() {
return mHeader;
}
@@ -314,41 +310,30 @@
return -1;
}
- private void highlightPreference(String key) {
- final Drawable highlight = getHighlightDrawable();
+ @Override
+ public RecyclerView.LayoutManager onCreateLayoutManager() {
+ mLayoutManager = new LinearLayoutManager(getContext());
+ return mLayoutManager;
+ }
+ @Override
+ protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
+ mAdapter = new HighlightablePreferenceGroupAdapter(preferenceScreen);
+ return mAdapter;
+ }
+
+ private void highlightPreference(String key) {
final int position = canUseListViewForHighLighting(key);
if (position >= 0) {
mPreferenceHighlighted = true;
+ mLayoutManager.scrollToPosition(position);
- // TODO: Need to find a way to scroll to and highlight search items now
- // that we are using RecyclerView instead.
-// final RecyclerView listView = getListView();
-// final RecyclerView.Adapter adapter = listView.getAdapter();
-//
-//// ((PreferenceGroupAdapter) adapter).setHighlightedDrawable(highlight);
-//// ((PreferenceGroupAdapter) adapter).setHighlighted(position);
-//
-// listView.post(new Runnable() {
-// @Override
-// public void run() {
-// listView.setSelection(position);
-// listView.postDelayed(new Runnable() {
-// @Override
-// public void run() {
-// final int index = position - listView.getFirstVisiblePosition();
-// if (index >= 0 && index < listView.getChildCount()) {
-// final View v = listView.getChildAt(index);
-// final int centerX = v.getWidth() / 2;
-// final int centerY = v.getHeight() / 2;
-// highlight.setHotspot(centerX, centerY);
-// v.setPressed(true);
-// v.setPressed(false);
-// }
-// }
-// }, DELAY_HIGHLIGHT_DURATION_MILLIS);
-// }
-// });
+ getView().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mAdapter.highlight(position);
+ }
+ }, DELAY_HIGHLIGHT_DURATION_MILLIS);
}
}
@@ -647,4 +632,34 @@
return false;
}
}
+
+ public static class HighlightablePreferenceGroupAdapter extends PreferenceGroupAdapter {
+
+ private int mHighlightPosition = -1;
+
+ public HighlightablePreferenceGroupAdapter(PreferenceGroup preferenceGroup) {
+ super(preferenceGroup);
+ }
+
+ public void highlight(int position) {
+ mHighlightPosition = position;
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder, int position) {
+ super.onBindViewHolder(holder, position);
+ if (position == mHighlightPosition) {
+ View v = holder.itemView;
+ if (v.getBackground() != null) {
+ final int centerX = v.getWidth() / 2;
+ final int centerY = v.getHeight() / 2;
+ v.getBackground().setHotspot(centerX, centerY);
+ }
+ v.setPressed(true);
+ v.setPressed(false);
+ mHighlightPosition = -1;
+ }
+ }
+ }
}
diff --git a/src/com/android/settings/SetupChooseLockGeneric.java b/src/com/android/settings/SetupChooseLockGeneric.java
index 0b0333b..9559f8d 100644
--- a/src/com/android/settings/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/SetupChooseLockGeneric.java
@@ -170,9 +170,9 @@
@Override
protected Intent getEncryptionInterstitialIntent(Context context, int quality,
- boolean required) {
+ boolean required, Intent unlockMethodIntent) {
Intent intent = SetupEncryptionInterstitial.createStartIntent(context, quality,
- required);
+ required, unlockMethodIntent);
SetupWizardUtils.copySetupExtras(getActivity().getIntent(), intent);
return intent;
}
diff --git a/src/com/android/settings/SetupEncryptionInterstitial.java b/src/com/android/settings/SetupEncryptionInterstitial.java
index cd943af..8d061ec 100644
--- a/src/com/android/settings/SetupEncryptionInterstitial.java
+++ b/src/com/android/settings/SetupEncryptionInterstitial.java
@@ -38,9 +38,9 @@
public class SetupEncryptionInterstitial extends EncryptionInterstitial {
public static Intent createStartIntent(Context ctx, int quality,
- boolean requirePasswordDefault) {
+ boolean requirePasswordDefault, Intent unlockMethodIntent) {
Intent startIntent = EncryptionInterstitial.createStartIntent(ctx, quality,
- requirePasswordDefault);
+ requirePasswordDefault, unlockMethodIntent);
startIntent.setClass(ctx, SetupEncryptionInterstitial.class);
startIntent.putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)
.putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, -1);
@@ -102,12 +102,7 @@
@Override
public void onNavigateNext() {
- final SetupEncryptionInterstitial activity =
- (SetupEncryptionInterstitial) getActivity();
- if (activity != null) {
- activity.setResult(RESULT_OK, activity.getResultIntentData());
- finish();
- }
+ startLockIntent();
}
}
}
diff --git a/src/com/android/settings/ShowAdminSupportDetailsDialog.java b/src/com/android/settings/ShowAdminSupportDetailsDialog.java
new file mode 100644
index 0000000..42e8f05
--- /dev/null
+++ b/src/com/android/settings/ShowAdminSupportDetailsDialog.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015 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;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+public class ShowAdminSupportDetailsDialog extends Activity
+ implements DialogInterface.OnDismissListener {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ View rootView = LayoutInflater.from(this).inflate(
+ R.layout.admin_support_details_dialog, null);
+ setAdminSupportDetails(rootView);
+
+ new AlertDialog.Builder(this)
+ .setView(rootView)
+ .setPositiveButton(R.string.okay, null)
+ .setOnDismissListener(this)
+ .show();
+ }
+
+ private void setAdminSupportDetails(View root) {
+ CharSequence adminDisabledMsg = getString(R.string.disabled_by_admin_msg,
+ getString(R.string.default_organisation_name));
+ TextView textView = (TextView) root.findViewById(R.id.disabled_by_admin_msg);
+ textView.setText(adminDisabledMsg);
+
+ CharSequence adminSupportDetails = getString(R.string.default_admin_support_msg);
+ textView = (TextView) root.findViewById(R.id.admin_support_msg);
+ textView.setText(adminSupportDetails);
+
+ root.findViewById(R.id.admins_policies_list).setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent();
+ intent.setClass(ShowAdminSupportDetailsDialog.this,
+ Settings.DeviceAdminSettingsActivity.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ }
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ finish();
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 5a54ba4..ddea92b 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -74,6 +74,7 @@
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
+import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -83,8 +84,6 @@
import android.widget.ListView;
import android.widget.TabWidget;
import com.android.internal.util.UserIcons;
-import com.android.settingslib.drawer.UserAdapter;
-import com.android.settingslib.drawer.UserAdapter.UserDetails;
import java.io.IOException;
import java.io.InputStream;
@@ -1058,5 +1057,11 @@
return UserHandle.myUserId();
}
}
+
+ public static int resolveResource(Context context, int attr) {
+ TypedValue value = new TypedValue();
+ context.getTheme().resolveAttribute(attr, value, true);
+ return value.resourceId;
+ }
}
diff --git a/src/com/android/settings/WifiCallingSettings.java b/src/com/android/settings/WifiCallingSettings.java
index d09c92c..e321372 100644
--- a/src/com/android/settings/WifiCallingSettings.java
+++ b/src/com/android/settings/WifiCallingSettings.java
@@ -35,7 +35,7 @@
import com.android.ims.ImsConfig;
import com.android.ims.ImsManager;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.telephony.imsphone.ImsPhone;
+import com.android.internal.telephony.Phone;
import com.android.settings.widget.SwitchBar;
/**
@@ -110,8 +110,8 @@
private void showAlert(Intent intent) {
Context context = getActivity();
- CharSequence title = intent.getCharSequenceExtra(ImsPhone.EXTRA_KEY_ALERT_TITLE);
- CharSequence message = intent.getCharSequenceExtra(ImsPhone.EXTRA_KEY_ALERT_MESSAGE);
+ CharSequence title = intent.getCharSequenceExtra(Phone.EXTRA_KEY_ALERT_TITLE);
+ CharSequence message = intent.getCharSequenceExtra(Phone.EXTRA_KEY_ALERT_MESSAGE);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage(message)
@@ -189,7 +189,7 @@
context.registerReceiver(mIntentReceiver, mIntentFilter);
Intent intent = getActivity().getIntent();
- if (intent.getBooleanExtra(ImsPhone.EXTRA_KEY_ALERT_SHOW, false)) {
+ if (intent.getBooleanExtra(Phone.EXTRA_KEY_ALERT_SHOW, false)) {
showAlert(intent);
}
}
diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java
index 55a2c32..27ab6a2 100644
--- a/src/com/android/settings/WirelessSettings.java
+++ b/src/com/android/settings/WirelessSettings.java
@@ -68,7 +68,6 @@
private static final String KEY_PROXY_SETTINGS = "proxy_settings";
private static final String KEY_MOBILE_NETWORK_SETTINGS = "mobile_network_settings";
private static final String KEY_MANAGE_MOBILE_PLAN = "manage_mobile_plan";
- private static final String KEY_CELL_BROADCAST_SETTINGS = "cell_broadcast_settings";
private static final String KEY_WFC_SETTINGS = "wifi_calling_settings";
public static final String EXIT_ECM_RESULT = "exit_ecm_result";
@@ -327,26 +326,6 @@
p.setEnabled(!TetherSettings
.isProvisioningNeededButUnavailable(getActivity()));
}
-
- // Enable link to CMAS app settings depending on the value in config.xml.
- boolean isCellBroadcastAppLinkEnabled = this.getResources().getBoolean(
- com.android.internal.R.bool.config_cellBroadcastAppLinks);
- try {
- if (isCellBroadcastAppLinkEnabled) {
- if (mPm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
- == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
- isCellBroadcastAppLinkEnabled = false; // CMAS app disabled
- }
- }
- } catch (IllegalArgumentException ignored) {
- isCellBroadcastAppLinkEnabled = false; // CMAS app not installed
- }
- if (!isAdmin || !isCellBroadcastAppLinkEnabled
- || mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS)) {
- PreferenceScreen root = getPreferenceScreen();
- Preference ps = findPreference(KEY_CELL_BROADCAST_SETTINGS);
- if (ps != null) root.removePreference(ps);
- }
}
@Override
@@ -478,23 +457,6 @@
result.add(KEY_TETHER_SETTINGS);
}
- // Enable link to CMAS app settings depending on the value in config.xml.
- boolean isCellBroadcastAppLinkEnabled = context.getResources().getBoolean(
- com.android.internal.R.bool.config_cellBroadcastAppLinks);
- try {
- if (isCellBroadcastAppLinkEnabled) {
- if (pm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
- == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
- isCellBroadcastAppLinkEnabled = false; // CMAS app disabled
- }
- }
- } catch (IllegalArgumentException ignored) {
- isCellBroadcastAppLinkEnabled = false; // CMAS app not installed
- }
- if (isSecondaryUser || !isCellBroadcastAppLinkEnabled) {
- result.add(KEY_CELL_BROADCAST_SETTINGS);
- }
-
return result;
}
};
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index b2ccdd1..672582d 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -85,6 +85,8 @@
"toggle_lock_screen_rotation_preference";
private static final String TOGGLE_SPEAK_PASSWORD_PREFERENCE =
"toggle_speak_password_preference";
+ private static final String TOGGLE_LARGE_POINTER_ICON =
+ "toggle_large_pointer_icon";
private static final String SELECT_LONG_PRESS_TIMEOUT_PREFERENCE =
"select_long_press_timeout_preference";
private static final String ENABLE_ACCESSIBILITY_GESTURE_PREFERENCE_SCREEN =
@@ -181,6 +183,7 @@
private SwitchPreference mTogglePowerButtonEndsCallPreference;
private SwitchPreference mToggleLockScreenRotationPreference;
private SwitchPreference mToggleSpeakPasswordPreference;
+ private SwitchPreference mToggleLargePointerIconPreference;
private ListPreference mSelectLongPressTimeoutPreference;
private Preference mNoServicesMessagePreference;
private PreferenceScreen mCaptioningPreferenceScreen;
@@ -278,6 +281,9 @@
} else if (mToggleSpeakPasswordPreference == preference) {
handleToggleSpeakPasswordPreferenceClick();
return true;
+ } else if (mToggleLargePointerIconPreference == preference) {
+ handleToggleLargePointerIconPreferenceClick();
+ return true;
} else if (mGlobalGesturePreferenceScreen == preference) {
handleToggleEnableAccessibilityGesturePreferenceClick();
return true;
@@ -322,6 +328,12 @@
mToggleSpeakPasswordPreference.isChecked() ? 1 : 0);
}
+ private void handleToggleLargePointerIconPreferenceClick() {
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON,
+ mToggleLargePointerIconPreference.isChecked() ? 1 : 0);
+ }
+
private void handleToggleEnableAccessibilityGesturePreferenceClick() {
Bundle extras = mGlobalGesturePreferenceScreen.getExtras();
extras.putString(EXTRA_TITLE, getString(
@@ -379,6 +391,10 @@
mToggleSpeakPasswordPreference =
(SwitchPreference) findPreference(TOGGLE_SPEAK_PASSWORD_PREFERENCE);
+ // Large pointer icon.
+ mToggleLargePointerIconPreference =
+ (SwitchPreference) findPreference(TOGGLE_LARGE_POINTER_ICON);
+
// Long press timeout.
mSelectLongPressTimeoutPreference =
(ListPreference) findPreference(SELECT_LONG_PRESS_TIMEOUT_PREFERENCE);
@@ -565,6 +581,10 @@
Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0) != 0;
mToggleSpeakPasswordPreference.setChecked(speakPasswordEnabled);
+ // Large pointer icon.
+ mToggleLargePointerIconPreference.setChecked(Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON, 0) != 0);
+
// Long press timeout.
final int longPressTimeout = Settings.Secure.getInt(getContentResolver(),
Settings.Secure.LONG_PRESS_TIMEOUT, mLongPressTimeoutDefault);
diff --git a/src/com/android/settings/applications/AppLaunchSettings.java b/src/com/android/settings/applications/AppLaunchSettings.java
index cbac4a1..ae711f7 100644
--- a/src/com/android/settings/applications/AppLaunchSettings.java
+++ b/src/com/android/settings/applications/AppLaunchSettings.java
@@ -26,6 +26,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
+import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.util.ArraySet;
@@ -34,7 +35,6 @@
import android.view.View.OnClickListener;
import com.android.internal.logging.MetricsLogger;
-import com.android.settings.DropDownPreference;
import com.android.settings.R;
import com.android.settings.Utils;
diff --git a/src/com/android/settings/applications/AppOpsCategory.java b/src/com/android/settings/applications/AppOpsCategory.java
index 3ccd6bb..4b54891 100644
--- a/src/com/android/settings/applications/AppOpsCategory.java
+++ b/src/com/android/settings/applications/AppOpsCategory.java
@@ -16,6 +16,7 @@
package com.android.settings.applications;
+import android.app.AppOpsManager;
import android.app.ListFragment;
import android.app.LoaderManager;
import android.content.AsyncTaskLoader;
@@ -34,6 +35,7 @@
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
+import android.widget.Switch;
import android.widget.TextView;
import com.android.settings.R;
@@ -48,6 +50,7 @@
private static final int RESULT_APP_DETAILS = 1;
AppOpsState mState;
+ boolean mUserControlled;
// This is the Adapter being used to display the list's data.
AppListAdapter mAdapter;
@@ -58,8 +61,13 @@
}
public AppOpsCategory(AppOpsState.OpsTemplate template) {
+ this(template, false);
+ }
+
+ public AppOpsCategory(AppOpsState.OpsTemplate template, boolean userControlled) {
Bundle args = new Bundle();
args.putParcelable("template", template);
+ args.putBoolean("userControlled", userControlled);
setArguments(args);
}
@@ -117,18 +125,22 @@
final InterestingConfigChanges mLastConfig = new InterestingConfigChanges();
final AppOpsState mState;
final AppOpsState.OpsTemplate mTemplate;
+ final boolean mUserControlled;
List<AppOpEntry> mApps;
PackageIntentReceiver mPackageObserver;
- public AppListLoader(Context context, AppOpsState state, AppOpsState.OpsTemplate template) {
+ public AppListLoader(Context context, AppOpsState state, AppOpsState.OpsTemplate template,
+ boolean userControlled) {
super(context);
mState = state;
mTemplate = template;
+ mUserControlled = userControlled;
}
@Override public List<AppOpEntry> loadInBackground() {
- return mState.buildState(mTemplate);
+ return mState.buildState(mTemplate, 0, null,
+ mUserControlled ? AppOpsState.LABEL_COMPARATOR : AppOpsState.RECENCY_COMPARATOR);
}
/**
@@ -247,13 +259,15 @@
private final Resources mResources;
private final LayoutInflater mInflater;
private final AppOpsState mState;
+ private final boolean mUserControlled;
List<AppOpEntry> mList;
- public AppListAdapter(Context context, AppOpsState state) {
+ public AppListAdapter(Context context, AppOpsState state, boolean userControlled) {
mResources = context.getResources();
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mState = state;
+ mUserControlled = userControlled;
}
public void setData(List<AppOpEntry> data) {
@@ -292,9 +306,18 @@
((ImageView)view.findViewById(R.id.app_icon)).setImageDrawable(
item.getAppEntry().getIcon());
((TextView)view.findViewById(R.id.app_name)).setText(item.getAppEntry().getLabel());
- ((TextView)view.findViewById(R.id.op_name)).setText(item.getSummaryText(mState));
- ((TextView)view.findViewById(R.id.op_time)).setText(
- item.getTimeText(mResources, false));
+ if (mUserControlled) {
+ ((TextView) view.findViewById(R.id.op_name)).setText(
+ item.getTimeText(mResources, false));
+ view.findViewById(R.id.op_time).setVisibility(View.GONE);
+ ((Switch) view.findViewById(R.id.op_switch)).setChecked(
+ item.getPrimaryOpMode() == AppOpsManager.MODE_ALLOWED);
+ } else {
+ ((TextView) view.findViewById(R.id.op_name)).setText(item.getSummaryText(mState));
+ ((TextView) view.findViewById(R.id.op_time)).setText(
+ item.getTimeText(mResources, false));
+ view.findViewById(R.id.op_switch).setVisibility(View.GONE);
+ }
return view;
}
@@ -304,6 +327,7 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mState = new AppOpsState(getActivity());
+ mUserControlled = getArguments().getBoolean("userControlled");
}
@Override public void onActivityCreated(Bundle savedInstanceState) {
@@ -317,7 +341,7 @@
setHasOptionsMenu(true);
// Create an empty adapter we will use to display the loaded data.
- mAdapter = new AppListAdapter(getActivity(), mState);
+ mAdapter = new AppListAdapter(getActivity(), mState, mUserControlled);
setListAdapter(mAdapter);
// Start out with a progress indicator.
@@ -341,8 +365,22 @@
@Override public void onListItemClick(ListView l, View v, int position, long id) {
AppOpEntry entry = mAdapter.getItem(position);
if (entry != null) {
- mCurrentPkgName = entry.getAppEntry().getApplicationInfo().packageName;
- startApplicationDetailsActivity();
+ if (mUserControlled) {
+ // We treat this as tapping on the check box, toggling the app op state.
+ Switch sw = ((Switch) v.findViewById(R.id.op_switch));
+ boolean checked = !sw.isChecked();
+ sw.setChecked(checked);
+ AppOpsManager.OpEntry op = entry.getOpEntry(0);
+ int mode = checked ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED;
+ mState.getAppOpsManager().setMode(op.getOp(),
+ entry.getAppEntry().getApplicationInfo().uid,
+ entry.getAppEntry().getApplicationInfo().packageName,
+ mode);
+ entry.overridePrimaryOpMode(mode);
+ } else {
+ mCurrentPkgName = entry.getAppEntry().getApplicationInfo().packageName;
+ startApplicationDetailsActivity();
+ }
}
}
@@ -352,7 +390,7 @@
if (fargs != null) {
template = (AppOpsState.OpsTemplate)fargs.getParcelable("template");
}
- return new AppListLoader(getActivity(), mState, template);
+ return new AppListLoader(getActivity(), mState, template, mUserControlled);
}
@Override public void onLoadFinished(Loader<List<AppOpEntry>> loader, List<AppOpEntry> data) {
diff --git a/src/com/android/settings/applications/AppOpsState.java b/src/com/android/settings/applications/AppOpsState.java
index c3189d6..237eac6 100644
--- a/src/com/android/settings/applications/AppOpsState.java
+++ b/src/com/android/settings/applications/AppOpsState.java
@@ -180,6 +180,7 @@
false,
false,
false,
+ false,
false }
);
@@ -206,9 +207,14 @@
false }
);
+ public static final OpsTemplate RUN_IN_BACKGROUND_TEMPLATE = new OpsTemplate(
+ new int[] { AppOpsManager.OP_RUN_IN_BACKGROUND },
+ new boolean[] { false }
+ );
+
public static final OpsTemplate[] ALL_TEMPLATES = new OpsTemplate[] {
LOCATION_TEMPLATE, PERSONAL_TEMPLATE, MESSAGING_TEMPLATE,
- MEDIA_TEMPLATE, DEVICE_TEMPLATE
+ MEDIA_TEMPLATE, DEVICE_TEMPLATE, RUN_IN_BACKGROUND_TEMPLATE
};
/**
@@ -306,6 +312,7 @@
= new ArrayList<AppOpsManager.OpEntry>();
private final AppEntry mApp;
private final int mSwitchOrder;
+ private int mOverriddenPrimaryMode = -1;
public AppOpEntry(AppOpsManager.PackageOps pkg, AppOpsManager.OpEntry op, AppEntry app,
int switchOrder) {
@@ -363,6 +370,14 @@
return mOps.get(pos);
}
+ public int getPrimaryOpMode() {
+ return mOverriddenPrimaryMode >= 0 ? mOverriddenPrimaryMode : mOps.get(0).getMode();
+ }
+
+ public void overridePrimaryOpMode(int mode) {
+ mOverriddenPrimaryMode = mode;
+ }
+
private CharSequence getCombinedText(ArrayList<AppOpsManager.OpEntry> ops,
CharSequence[] items) {
if (ops.size() == 1) {
@@ -418,9 +433,9 @@
}
/**
- * Perform alphabetical comparison of application entry objects.
+ * Perform app op state comparison of application entry objects.
*/
- public static final Comparator<AppOpEntry> APP_OP_COMPARATOR = new Comparator<AppOpEntry>() {
+ public static final Comparator<AppOpEntry> RECENCY_COMPARATOR = new Comparator<AppOpEntry>() {
private final Collator sCollator = Collator.getInstance();
@Override
public int compare(AppOpEntry object1, AppOpEntry object2) {
@@ -440,6 +455,18 @@
}
};
+ /**
+ * Perform alphabetical comparison of application entry objects.
+ */
+ public static final Comparator<AppOpEntry> LABEL_COMPARATOR = new Comparator<AppOpEntry>() {
+ private final Collator sCollator = Collator.getInstance();
+ @Override
+ public int compare(AppOpEntry object1, AppOpEntry object2) {
+ return sCollator.compare(object1.getAppEntry().getLabel(),
+ object2.getAppEntry().getLabel());
+ }
+ };
+
private void addOp(List<AppOpEntry> entries, AppOpsManager.PackageOps pkgOps,
AppEntry appEntry, AppOpsManager.OpEntry opEntry, boolean allowMerge, int switchOrder) {
if (allowMerge && entries.size() > 0) {
@@ -466,8 +493,12 @@
entries.add(entry);
}
+ public AppOpsManager getAppOpsManager() {
+ return mAppOps;
+ }
+
public List<AppOpEntry> buildState(OpsTemplate tpl) {
- return buildState(tpl, 0, null);
+ return buildState(tpl, 0, null, RECENCY_COMPARATOR);
}
private AppEntry getAppEntry(final Context context, final HashMap<String, AppEntry> appEntries,
@@ -492,6 +523,11 @@
}
public List<AppOpEntry> buildState(OpsTemplate tpl, int uid, String packageName) {
+ return buildState(tpl, uid, packageName, RECENCY_COMPARATOR);
+ }
+
+ public List<AppOpEntry> buildState(OpsTemplate tpl, int uid, String packageName,
+ Comparator<AppOpEntry> comparator) {
final Context context = mContext;
final HashMap<String, AppEntry> appEntries = new HashMap<String, AppEntry>();
@@ -593,7 +629,7 @@
}
// Sort the list.
- Collections.sort(entries, APP_OP_COMPARATOR);
+ Collections.sort(entries, comparator);
// Done!
return entries;
diff --git a/src/com/android/settings/applications/BackgroundCheckSummary.java b/src/com/android/settings/applications/BackgroundCheckSummary.java
new file mode 100644
index 0000000..dfd4c49
--- /dev/null
+++ b/src/com/android/settings/applications/BackgroundCheckSummary.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (C) 2015 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.applications;
+
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.res.TypedArray;
+import android.os.Bundle;
+import android.preference.PreferenceFrameLayout;
+import android.support.v13.app.FragmentPagerAdapter;
+import android.support.v4.view.PagerTabStrip;
+import android.support.v4.view.ViewPager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.R;
+
+public class BackgroundCheckSummary extends InstrumentedFragment {
+ // layout inflater object used to inflate views
+ private LayoutInflater mInflater;
+
+ @Override
+ protected int getMetricsCategory() {
+ return MetricsLogger.BACKGROUND_CHECK_SUMMARY;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ // initialize the inflater
+ mInflater = inflater;
+
+ View rootView = mInflater.inflate(R.layout.background_check_summary,
+ container, false);
+
+ // We have to do this now because PreferenceFrameLayout looks at it
+ // only when the view is added.
+ if (container instanceof PreferenceFrameLayout) {
+ ((PreferenceFrameLayout.LayoutParams) rootView.getLayoutParams()).removeBorders = true;
+ }
+
+ FragmentTransaction ft = getChildFragmentManager().beginTransaction();
+ ft.add(R.id.appops_content, new AppOpsCategory(AppOpsState.RUN_IN_BACKGROUND_TEMPLATE,
+ true), "appops");
+ ft.commitAllowingStateLoss();
+
+ return rootView;
+ }
+}
diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java
index 6228bbc..a53d8b6 100644
--- a/src/com/android/settings/dashboard/DashboardAdapter.java
+++ b/src/com/android/settings/dashboard/DashboardAdapter.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
-import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
@@ -26,40 +25,52 @@
import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.util.ArrayUtils;
+import com.android.settings.R;
import com.android.settings.SettingsActivity;
+import com.android.settings.dashboard.conditional.Condition;
+import com.android.settings.dashboard.conditional.ConditionAdapterUtils;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.DashboardTile;
import java.util.ArrayList;
import java.util.List;
-public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.DashboardItemHolder> {
+public class DashboardAdapter extends RecyclerView.Adapter<DashboardAdapter.DashboardItemHolder> implements View.OnClickListener {
public static final String TAG = "DashboardAdapter";
private final List<Object> mItems = new ArrayList<>();
private final List<Integer> mTypes = new ArrayList<>();
private final List<Integer> mIds = new ArrayList<>();
- private final List<DashboardCategory> mCategories;
private final Context mContext;
+ private List<DashboardCategory> mCategories;
+ private List<Condition> mConditions;
+
private boolean mIsShowingAll;
// Used for counting items;
private int mId;
- public DashboardAdapter(Context context, List<DashboardCategory> categories) {
+ private Condition mExpandedCondition = null;
+
+ public DashboardAdapter(Context context) {
mContext = context;
+
+ setHasStableIds(true);
+ }
+
+ public void setCategories(List<DashboardCategory> categories) {
mCategories = categories;
// TODO: Better place for tinting?
TypedValue tintColor = new TypedValue();
- context.getTheme().resolveAttribute(com.android.internal.R.attr.colorAccent,
+ mContext.getTheme().resolveAttribute(com.android.internal.R.attr.colorAccent,
tintColor, true);
for (int i = 0; i < categories.size(); i++) {
for (int j = 0; j < categories.get(i).tiles.size(); j++) {
DashboardTile tile = categories.get(i).tiles.get(j);
- if (!context.getPackageName().equals(
+ if (!mContext.getPackageName().equals(
tile.intent.getComponent().getPackageName())) {
// If this drawable is coming from outside Settings, tint it to match the
// color.
@@ -67,9 +78,12 @@
}
}
}
+ setShowingAll(mIsShowingAll);
+ }
- setShowingAll(false);
- setHasStableIds(true);
+ public void setConditions(List<Condition> conditions) {
+ mConditions = conditions;
+ setShowingAll(mIsShowingAll);
}
public boolean isShowingAll() {
@@ -77,30 +91,27 @@
}
public void notifyChanged(DashboardTile tile) {
- for (int i = 0; i < mItems.size(); i++) {
- if (mItems.get(i) == tile) {
- notifyItemChanged(i);
- return;
- }
- }
+ notifyDataSetChanged();
}
public void setShowingAll(boolean showingAll) {
mIsShowingAll = showingAll;
reset();
- countItem(null, com.android.settings.R.layout.dashboard_spacer, true);
- for (int i = 0; i < mCategories.size(); i++) {
+ for (int i = 0; mConditions != null && i < mConditions.size(); i++) {
+ countItem(mConditions.get(i), R.layout.condition_card, mConditions.get(i).shouldShow());
+ }
+ countItem(null, R.layout.dashboard_spacer, true);
+ for (int i = 0; mCategories != null && i < mCategories.size(); i++) {
DashboardCategory category = mCategories.get(i);
- countItem(category, com.android.settings.R.layout.dashboard_category, mIsShowingAll);
+ countItem(category, R.layout.dashboard_category, mIsShowingAll);
for (int j = 0; j < category.tiles.size(); j++) {
DashboardTile tile = category.tiles.get(j);
- Log.d(TAG, "Maybe adding " + tile.intent.getComponent().getClassName());
- countItem(tile, com.android.settings.R.layout.dashboard_tile, mIsShowingAll
+ countItem(tile, R.layout.dashboard_tile, mIsShowingAll
|| ArrayUtils.contains(DashboardSummary.INITIAL_ITEMS,
tile.intent.getComponent().getClassName()));
}
}
- countItem(null, com.android.settings.R.layout.see_all, true);
+ countItem(null, R.layout.see_all, true);
notifyDataSetChanged();
}
@@ -129,10 +140,10 @@
@Override
public void onBindViewHolder(DashboardItemHolder holder, int position) {
switch (mTypes.get(position)) {
- case com.android.settings.R.layout.dashboard_category:
+ case R.layout.dashboard_category:
onBindCategory(holder, (DashboardCategory) mItems.get(position));
break;
- case com.android.settings.R.layout.dashboard_tile:
+ case R.layout.dashboard_tile:
final DashboardTile tile = (DashboardTile) mItems.get(position);
onBindTile(holder, tile);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@@ -142,7 +153,7 @@
}
});
break;
- case com.android.settings.R.layout.see_all:
+ case R.layout.see_all:
onBindSeeAll(holder);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
@@ -151,6 +162,16 @@
}
});
break;
+ case R.layout.condition_card:
+ ConditionAdapterUtils.bindViews((Condition) mItems.get(position), holder,
+ mItems.get(position) == mExpandedCondition, this,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onExpandClick(v);
+ }
+ });
+ break;
}
}
@@ -170,8 +191,8 @@
}
private void onBindSeeAll(DashboardItemHolder holder) {
- holder.title.setText(mIsShowingAll ? com.android.settings.R.string.see_less
- : com.android.settings.R.string.see_all);
+ holder.title.setText(mIsShowingAll ? R.string.see_less
+ : R.string.see_all);
}
@Override
@@ -189,10 +210,38 @@
return mIds.size();
}
+ @Override
+ public void onClick(View v) {
+ if (v.getTag() == mExpandedCondition) {
+ mExpandedCondition.onPrimaryClick();
+ } else {
+ mExpandedCondition = (Condition) v.getTag();
+ notifyDataSetChanged();
+ }
+ }
+
+ public void onExpandClick(View v) {
+ if (v.getTag() == mExpandedCondition) {
+ mExpandedCondition = null;
+ } else {
+ mExpandedCondition = (Condition) v.getTag();
+ }
+ notifyDataSetChanged();
+ }
+
+ public Object getItem(long itemId) {
+ for (int i = 0; i < mIds.size(); i++) {
+ if (mIds.get(i) == itemId) {
+ return mItems.get(i);
+ }
+ }
+ return null;
+ }
+
public static class DashboardItemHolder extends RecyclerView.ViewHolder {
- private final ImageView icon;
- private final TextView title;
- private final TextView summary;
+ public final ImageView icon;
+ public final TextView title;
+ public final TextView summary;
public DashboardItemHolder(View itemView) {
super(itemView);
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
index 54a5ff4..95170a4 100644
--- a/src/com/android/settings/dashboard/DashboardSummary.java
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -16,15 +16,8 @@
package com.android.settings.dashboard;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -37,12 +30,19 @@
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.SettingsActivity;
+import com.android.settings.dashboard.conditional.ConditionAdapterUtils;
+import com.android.settings.dashboard.conditional.ConditionManager;
+import com.android.settings.dashboard.conditional.FocusRecyclerView;
import com.android.settingslib.drawer.DashboardCategory;
+import com.android.settingslib.drawer.SettingsDrawerActivity;
import java.util.List;
-public class DashboardSummary extends InstrumentedFragment {
- public static final boolean DEBUG = true;
+public class DashboardSummary extends InstrumentedFragment
+ implements SettingsDrawerActivity.CategoryListener, ConditionManager.ConditionListener,
+ FocusRecyclerView.FocusListener {
+ public static final boolean DEBUG = false;
+ private static final boolean DEBUG_TIMING = false;
private static final String TAG = "DashboardSummary";
public static final String[] INITIAL_ITEMS = new String[] {
@@ -54,13 +54,10 @@
Settings.StorageSettingsActivity.class.getName(),
};
- private static final int MSG_REBUILD_UI = 1;
-
- private final HomePackageReceiver mHomePackageReceiver = new HomePackageReceiver();
-
- private RecyclerView mDashboard;
+ private FocusRecyclerView mDashboard;
private DashboardAdapter mAdapter;
private SummaryLoader mSummaryLoader;
+ private ConditionManager mConditionManager;
@Override
protected int getMetricsCategory() {
@@ -71,11 +68,20 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ long startTime = System.currentTimeMillis();
List<DashboardCategory> categories =
- ((SettingsActivity) getActivity()).getDashboardCategories(true);
- mAdapter = new DashboardAdapter(getContext(), categories);
- mSummaryLoader = new SummaryLoader(getActivity(), mAdapter, categories);
+ ((SettingsActivity) getActivity()).getDashboardCategories();
+ mSummaryLoader = new SummaryLoader(getActivity(), categories);
setHasOptionsMenu(true);
+ if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
+ + " ms");
+ mConditionManager = ConditionManager.get(getContext());
+ }
+
+ @Override
+ public void onDestroy() {
+ mSummaryLoader.release();
+ super.onDestroy();
}
@Override
@@ -90,26 +96,30 @@
public void onResume() {
super.onResume();
- sendRebuildUI();
-
- final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
- filter.addDataScheme("package");
- getActivity().registerReceiver(mHomePackageReceiver, filter);
+ ((SettingsDrawerActivity) getActivity()).addCategoryListener(this);
mSummaryLoader.setListening(true);
+ Log.d(TAG, "onResume");
}
@Override
public void onPause() {
super.onPause();
- getActivity().unregisterReceiver(mHomePackageReceiver);
+ ((SettingsDrawerActivity) getActivity()).remCategoryListener(this);
mSummaryLoader.setListening(false);
}
@Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ if (hasWindowFocus) {
+ mConditionManager.addListener(this);
+ mConditionManager.refreshAll();
+ } else {
+ mConditionManager.remListener(this);
+ }
+ }
+
+ @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.dashboard, container, false);
@@ -117,16 +127,21 @@
@Override
public void onViewCreated(View view, Bundle bundle) {
- mDashboard = (RecyclerView) view.findViewById(R.id.dashboard_container);
+ mDashboard = (FocusRecyclerView) view.findViewById(R.id.dashboard_container);
LinearLayoutManager llm = new LinearLayoutManager(getContext());
llm.setOrientation(LinearLayoutManager.VERTICAL);
mDashboard.setLayoutManager(llm);
mDashboard.setHasFixedSize(true);
+ mDashboard.setListener(this);
+ mAdapter = new DashboardAdapter(getContext());
+ mAdapter.setConditions(mConditionManager.getConditions());
+ mSummaryLoader.setAdapter(mAdapter);
+ ConditionAdapterUtils.addDismiss(mDashboard);
- rebuildUI(getContext());
+ rebuildUI();
}
- private void rebuildUI(Context context) {
+ private void rebuildUI() {
if (!isAdded()) {
Log.w(TAG, "Cannot build the DashboardSummary UI yet as the Fragment is not added");
return;
@@ -135,40 +150,22 @@
long start = System.currentTimeMillis();
// TODO: Cache summaries from old categories somehow.
List<DashboardCategory> categories =
- ((SettingsActivity) getActivity()).getDashboardCategories(true);
- boolean showingAll = mAdapter != null && mAdapter.isShowingAll();
- mAdapter = new DashboardAdapter(getContext(), categories);
- mSummaryLoader.setAdapter(mAdapter);
- mAdapter.setShowingAll(showingAll);
+ ((SettingsActivity) getActivity()).getDashboardCategories();
+ mAdapter.setCategories(categories);
mDashboard.setAdapter(mAdapter);
long delta = System.currentTimeMillis() - start;
Log.d(TAG, "rebuildUI took: " + delta + " ms");
}
- private void sendRebuildUI() {
- if (!mHandler.hasMessages(MSG_REBUILD_UI)) {
- mHandler.sendEmptyMessage(MSG_REBUILD_UI);
- }
+ @Override
+ public void onCategoriesChanged() {
+ rebuildUI();
}
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_REBUILD_UI: {
- final Context context = getActivity();
- rebuildUI(context);
- } break;
- }
- }
- };
-
- private class HomePackageReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- rebuildUI(context);
- }
+ @Override
+ public void onConditionsChanged() {
+ Log.d(TAG, "onConditionsChanged");
+ mAdapter.setConditions(mConditionManager.getConditions());
}
-
}
diff --git a/src/com/android/settings/dashboard/SummaryLoader.java b/src/com/android/settings/dashboard/SummaryLoader.java
index a5481ac..a9dd43a 100644
--- a/src/com/android/settings/dashboard/SummaryLoader.java
+++ b/src/com/android/settings/dashboard/SummaryLoader.java
@@ -16,9 +16,11 @@
package com.android.settings.dashboard;
import android.app.Activity;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
import android.util.ArrayMap;
import android.util.Log;
import com.android.settings.SettingsActivity;
@@ -39,38 +41,48 @@
private final ArrayMap<SummaryProvider, DashboardTile> mSummaryMap = new ArrayMap<>();
private final List<DashboardTile> mTiles = new ArrayList<>();
+ private final Worker mWorker;
+ private final Handler mHandler;
+ private final HandlerThread mWorkerThread;
+
private DashboardAdapter mAdapter;
- public SummaryLoader(Activity activity, DashboardAdapter adapter,
- List<DashboardCategory> categories) {
+ public SummaryLoader(Activity activity, List<DashboardCategory> categories) {
+ mHandler = new Handler();
+ mWorkerThread = new HandlerThread("SummaryLoader");
+ mWorkerThread.start();
+ mWorker = new Worker(mWorkerThread.getLooper());
mActivity = activity;
- mAdapter = adapter;
for (int i = 0; i < categories.size(); i++) {
List<DashboardTile> tiles = categories.get(i).tiles;
for (int j = 0; j < tiles.size(); j++) {
DashboardTile tile = tiles.get(j);
- SummaryProvider provider = getSummaryProvider(tile);
- if (provider != null) {
- mSummaryMap.put(provider, tile);
- }
+ mWorker.obtainMessage(Worker.MSG_GET_PROVIDER, tile).sendToTarget();
}
}
}
+ public void release() {
+ mWorkerThread.quit();
+ }
+
public void setAdapter(DashboardAdapter adapter) {
mAdapter = adapter;
}
- public void setSummary(SummaryProvider provider, CharSequence summary) {
- DashboardTile tile = mSummaryMap.get(provider);
- tile.summary = summary;
- mAdapter.notifyChanged(tile);
+ public void setSummary(SummaryProvider provider, final CharSequence summary) {
+ final DashboardTile tile = mSummaryMap.get(provider);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ tile.summary = summary;
+ mAdapter.notifyChanged(tile);
+ }
+ });
}
public void setListening(boolean listening) {
- for (SummaryProvider provider : mSummaryMap.keySet()) {
- provider.setListening(listening);
- }
+ mWorker.obtainMessage(Worker.MSG_SET_LISTENING, listening ? 1 : 0, 0).sendToTarget();
}
private SummaryProvider getSummaryProvider(DashboardTile tile) {
@@ -107,14 +119,7 @@
}
private Bundle getMetaData(DashboardTile tile) {
- // TODO: Cache this in TileUtils so this doesn't need to be loaded again.
- try {
- ActivityInfo activityInfo = mActivity.getPackageManager().getActivityInfo(
- tile.intent.getComponent(), PackageManager.GET_META_DATA);
- return activityInfo.metaData;
- } catch (PackageManager.NameNotFoundException e) {
- return null;
- }
+ return tile.metaData;
}
public interface SummaryProvider {
@@ -124,4 +129,34 @@
public interface SummaryProviderFactory {
SummaryProvider createSummaryProvider(Activity activity, SummaryLoader summaryLoader);
}
+
+ private class Worker extends Handler {
+ private static final int MSG_GET_PROVIDER = 1;
+ private static final int MSG_SET_LISTENING = 2;
+
+ public Worker(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_GET_PROVIDER:
+ DashboardTile tile = (DashboardTile) msg.obj;
+ SummaryProvider provider = getSummaryProvider(tile);
+ if (provider != null) {
+ if (DEBUG) Log.d(TAG, "Creating " + tile);
+ mSummaryMap.put(provider, tile);
+ }
+ break;
+ case MSG_SET_LISTENING:
+ boolean listening = msg.arg1 != 0;
+ if (DEBUG) Log.d(TAG, "Listening " + listening);
+ for (SummaryProvider p : mSummaryMap.keySet()) {
+ p.setListening(listening);
+ }
+ break;
+ }
+ }
+ }
}
diff --git a/src/com/android/settings/dashboard/conditional/AirplaneModeCondition.java b/src/com/android/settings/dashboard/conditional/AirplaneModeCondition.java
new file mode 100644
index 0000000..5b9bb40
--- /dev/null
+++ b/src/com/android/settings/dashboard/conditional/AirplaneModeCondition.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015 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.dashboard.conditional;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.net.ConnectivityManager;
+import com.android.settings.R;
+import com.android.settings.Settings;
+import com.android.settingslib.WirelessUtils;
+
+public class AirplaneModeCondition extends Condition {
+
+ public AirplaneModeCondition(ConditionManager conditionManager) {
+ super(conditionManager);
+ }
+
+ @Override
+ public void refreshState() {
+ setActive(WirelessUtils.isAirplaneModeOn(mManager.getContext()));
+ }
+
+ @Override
+ protected Class<?> getReceiverClass() {
+ return Receiver.class;
+ }
+
+ @Override
+ public Icon getIcon() {
+ return Icon.createWithResource(mManager.getContext(), R.drawable.ic_airplane);
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return mManager.getContext().getString(R.string.condition_airplane_title);
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return mManager.getContext().getString(R.string.condition_airplane_summary);
+ }
+
+ @Override
+ public CharSequence[] getActions() {
+ return new CharSequence[] { mManager.getContext().getString(R.string.condition_turn_off) };
+ }
+
+ @Override
+ public void onPrimaryClick() {
+ mManager.getContext().startActivity(new Intent(mManager.getContext(),
+ Settings.WirelessSettingsActivity.class));
+ }
+
+ @Override
+ public void onActionClick(int index) {
+ if (index == 0) {
+ ConnectivityManager.from(mManager.getContext()).setAirplaneMode(false);
+ setActive(false);
+ } else {
+ throw new IllegalArgumentException("Unexpected index " + index);
+ }
+ }
+
+ public static class Receiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(intent.getAction())) {
+ ConditionManager.get(context).getCondition(AirplaneModeCondition.class)
+ .refreshState();
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/dashboard/conditional/BackgroundDataCondition.java b/src/com/android/settings/dashboard/conditional/BackgroundDataCondition.java
new file mode 100644
index 0000000..d1bcb12
--- /dev/null
+++ b/src/com/android/settings/dashboard/conditional/BackgroundDataCondition.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2015 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.dashboard.conditional;
+
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.net.NetworkPolicyManager;
+import com.android.settings.R;
+import com.android.settings.Settings;
+
+public class BackgroundDataCondition extends Condition {
+
+ public BackgroundDataCondition(ConditionManager manager) {
+ super(manager);
+ }
+
+ @Override
+ public void refreshState() {
+ setActive(NetworkPolicyManager.from(mManager.getContext()).getRestrictBackground());
+ }
+
+ @Override
+ public Icon getIcon() {
+ return Icon.createWithResource(mManager.getContext(), R.drawable.ic_cellular_off);
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return mManager.getContext().getString(R.string.condition_bg_data_title);
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return mManager.getContext().getString(R.string.condition_bg_data_summary);
+ }
+
+ @Override
+ public CharSequence[] getActions() {
+ return new CharSequence[] { mManager.getContext().getString(R.string.condition_turn_off) };
+ }
+
+ @Override
+ public void onPrimaryClick() {
+ mManager.getContext().startActivity(new Intent(mManager.getContext(),
+ Settings.DataUsageSummaryActivity.class));
+ }
+
+ @Override
+ public void onActionClick(int index) {
+ if (index == 0) {
+ NetworkPolicyManager.from(mManager.getContext()).setRestrictBackground(false);
+ setActive(false);
+ } else {
+ throw new IllegalArgumentException("Unexpected index " + index);
+ }
+ }
+}
diff --git a/src/com/android/settings/dashboard/conditional/BatterySaverCondition.java b/src/com/android/settings/dashboard/conditional/BatterySaverCondition.java
new file mode 100644
index 0000000..d902b04
--- /dev/null
+++ b/src/com/android/settings/dashboard/conditional/BatterySaverCondition.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2015 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.dashboard.conditional;
+
+import android.graphics.drawable.Icon;
+import android.os.PowerManager;
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.fuelgauge.BatterySaverSettings;
+
+public class BatterySaverCondition extends Condition {
+ public BatterySaverCondition(ConditionManager manager) {
+ super(manager);
+ }
+
+ @Override
+ public void refreshState() {
+ PowerManager powerManager = mManager.getContext().getSystemService(PowerManager.class);
+ setActive(powerManager.isPowerSaveMode());
+ }
+
+ @Override
+ public Icon getIcon() {
+ return Icon.createWithResource(mManager.getContext(), R.drawable.ic_settings_battery);
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return mManager.getContext().getString(R.string.condition_battery_title);
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return mManager.getContext().getString(R.string.condition_battery_summary);
+ }
+
+ @Override
+ public CharSequence[] getActions() {
+ return new CharSequence[] { mManager.getContext().getString(R.string.condition_turn_off) };
+ }
+
+ @Override
+ public void onPrimaryClick() {
+ Utils.startWithFragment(mManager.getContext(), BatterySaverSettings.class.getName(), null,
+ null, 0, R.string.battery_saver, null);
+ }
+
+ @Override
+ public void onActionClick(int index) {
+ if (index == 0) {
+ mManager.getContext().getSystemService(PowerManager.class).setPowerSaveMode(false);
+ refreshState();
+ } else {
+ throw new IllegalArgumentException("Unexpected index " + index);
+ }
+ }
+}
diff --git a/src/com/android/settings/dashboard/conditional/CellularDataCondition.java b/src/com/android/settings/dashboard/conditional/CellularDataCondition.java
new file mode 100644
index 0000000..edf5b21
--- /dev/null
+++ b/src/com/android/settings/dashboard/conditional/CellularDataCondition.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2015 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.dashboard.conditional;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.net.ConnectivityManager;
+import android.telephony.TelephonyManager;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.settings.R;
+import com.android.settings.Settings;
+
+public class CellularDataCondition extends Condition {
+
+ public CellularDataCondition(ConditionManager manager) {
+ super(manager);
+ }
+
+ @Override
+ public void refreshState() {
+ ConnectivityManager connectivity = mManager.getContext().getSystemService(
+ ConnectivityManager.class);
+ TelephonyManager telephony = mManager.getContext().getSystemService(TelephonyManager.class);
+ if (!connectivity.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)
+ || telephony.getSimState() != TelephonyManager.SIM_STATE_READY) {
+ setActive(false);
+ return;
+ }
+ setActive(!telephony.getDataEnabled());
+ }
+
+ @Override
+ protected Class<?> getReceiverClass() {
+ return Receiver.class;
+ }
+
+ @Override
+ public Icon getIcon() {
+ return Icon.createWithResource(mManager.getContext(), R.drawable.ic_cellular_off);
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return mManager.getContext().getString(R.string.condition_cellular_title);
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return mManager.getContext().getString(R.string.condition_cellular_summary);
+ }
+
+ @Override
+ public CharSequence[] getActions() {
+ return new CharSequence[] { mManager.getContext().getString(R.string.condition_turn_on) };
+ }
+
+ @Override
+ public void onPrimaryClick() {
+ mManager.getContext().startActivity(new Intent(mManager.getContext(),
+ Settings.DataUsageSummaryActivity.class));
+ }
+
+ @Override
+ public void onActionClick(int index) {
+ if (index == 0) {
+ TelephonyManager telephony = mManager.getContext().getSystemService(
+ TelephonyManager.class);
+ telephony.setDataEnabled(true);
+ setActive(false);
+ } else {
+ throw new IllegalArgumentException("Unexpected index " + index);
+ }
+ }
+
+ public static class Receiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED.equals(
+ intent.getAction())) {
+ ConditionManager.get(context).getCondition(CellularDataCondition.class)
+ .refreshState();
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/dashboard/conditional/Condition.java b/src/com/android/settings/dashboard/conditional/Condition.java
new file mode 100644
index 0000000..f5040e5
--- /dev/null
+++ b/src/com/android/settings/dashboard/conditional/Condition.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 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.dashboard.conditional;
+
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Icon;
+import android.os.PersistableBundle;
+
+public abstract class Condition {
+
+ private static final String KEY_SILENCE = "silence";
+ private static final String KEY_ACTIVE = "active";
+ private static final String KEY_LAST_STATE = "last_state";
+
+ protected final ConditionManager mManager;
+
+ private boolean mIsSilenced;
+ private boolean mIsActive;
+ private long mLastStateChange;
+
+ public Condition(ConditionManager manager) {
+ mManager = manager;
+ }
+
+ void restoreState(PersistableBundle bundle) {
+ mIsSilenced = bundle.getBoolean(KEY_SILENCE);
+ mIsActive = bundle.getBoolean(KEY_ACTIVE);
+ mLastStateChange = bundle.getLong(KEY_LAST_STATE);
+ }
+
+ void saveState(PersistableBundle bundle) {
+ bundle.putBoolean(KEY_SILENCE, mIsSilenced);
+ bundle.putBoolean(KEY_ACTIVE, mIsActive);
+ bundle.putLong(KEY_LAST_STATE, mLastStateChange);
+ }
+
+ protected void notifyChanged() {
+ mManager.notifyChanged(this);
+ }
+
+ public boolean isSilenced() {
+ return mIsSilenced;
+ }
+
+ public boolean isActive() {
+ return mIsActive;
+ }
+
+ protected void setActive(boolean active) {
+ if (mIsActive == active) {
+ return;
+ }
+ mIsActive = active;
+ mLastStateChange = System.currentTimeMillis();
+ if (mIsSilenced && !active) {
+ mIsSilenced = false;
+ onSilenceChanged(mIsSilenced);
+ }
+ notifyChanged();
+ }
+
+ public void silence() {
+ if (!mIsSilenced) {
+ mIsSilenced = true;
+ onSilenceChanged(mIsSilenced);
+ notifyChanged();
+ }
+ }
+
+ private void onSilenceChanged(boolean silenced) {
+ Class<?> clz = getReceiverClass();
+ if (clz == null) {
+ return;
+ }
+ // Only need to listen for changes when its been silenced.
+ PackageManager pm = mManager.getContext().getPackageManager();
+ pm.setComponentEnabledSetting(new ComponentName(mManager.getContext(), clz),
+ silenced ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
+ }
+
+ protected Class<?> getReceiverClass() {
+ return null;
+ }
+
+ public boolean shouldShow() {
+ return isActive() && !isSilenced();
+ }
+
+ long getLastChange() {
+ return mLastStateChange;
+ }
+
+ // State.
+ public abstract void refreshState();
+
+ // UI.
+ public abstract Icon getIcon();
+ public abstract CharSequence getTitle();
+ public abstract CharSequence getSummary();
+ public abstract CharSequence[] getActions();
+
+ public abstract void onPrimaryClick();
+ public abstract void onActionClick(int index);
+}
diff --git a/src/com/android/settings/dashboard/conditional/ConditionAdapterUtils.java b/src/com/android/settings/dashboard/conditional/ConditionAdapterUtils.java
new file mode 100644
index 0000000..e390782
--- /dev/null
+++ b/src/com/android/settings/dashboard/conditional/ConditionAdapterUtils.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 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.dashboard.conditional;
+
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.helper.ItemTouchHelper;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardAdapter;
+
+public class ConditionAdapterUtils {
+
+ public static void addDismiss(final RecyclerView recyclerView) {
+ ItemTouchHelper.SimpleCallback callback = new ItemTouchHelper.SimpleCallback(0,
+ ItemTouchHelper.START | ItemTouchHelper.END) {
+ @Override
+ public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
+ RecyclerView.ViewHolder target) {
+ return true;
+ }
+
+ @Override
+ public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
+ return viewHolder.getItemViewType() == R.layout.condition_card
+ ? super.getSwipeDirs(recyclerView, viewHolder) : 0;
+ }
+
+ @Override
+ public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
+ DashboardAdapter adapter = (DashboardAdapter) recyclerView.getAdapter();
+ Object item = adapter.getItem(viewHolder.getItemId());
+ if (item instanceof Condition) {
+ ((Condition) item).silence();
+ }
+ }
+ };
+ ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
+ itemTouchHelper.attachToRecyclerView(recyclerView);
+ }
+
+ public static void bindViews(final Condition condition,
+ DashboardAdapter.DashboardItemHolder view, boolean isExpanded,
+ View.OnClickListener onClickListener, View.OnClickListener onExpandListener) {
+ view.itemView.setTag(condition);
+ view.itemView.setOnClickListener(onClickListener);
+ view.icon.setImageIcon(condition.getIcon());
+ view.title.setText(condition.getTitle());
+ ImageView expand = (ImageView) view.itemView.findViewById(R.id.expand_indicator);
+ expand.setTag(condition);
+ expand.setImageResource(isExpanded ? R.drawable.ic_expand_less : R.drawable.ic_expand_more);
+ expand.setOnClickListener(onExpandListener);
+
+ View detailGroup = view.itemView.findViewById(R.id.detail_group);
+ // TODO: Animate expand/collapse
+ detailGroup.setVisibility(isExpanded ? View.VISIBLE : View.GONE);
+ if (isExpanded) {
+ view.summary.setText(condition.getSummary());
+ CharSequence[] actions = condition.getActions();
+ for (int i = 0; i < 2; i++) {
+ Button button = (Button) detailGroup.findViewById(i == 0
+ ? R.id.first_action : R.id.second_action);
+ if (actions.length > i) {
+ button.setVisibility(View.VISIBLE);
+ button.setText(actions[i]);
+ final int index = i;
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ condition.onActionClick(index);
+ }
+ });
+ } else {
+ button.setVisibility(View.GONE);
+ }
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/dashboard/conditional/ConditionManager.java b/src/com/android/settings/dashboard/conditional/ConditionManager.java
new file mode 100644
index 0000000..a245222
--- /dev/null
+++ b/src/com/android/settings/dashboard/conditional/ConditionManager.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2015 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.dashboard.conditional;
+
+import android.content.Context;
+import android.os.PersistableBundle;
+import android.util.Log;
+import android.util.Xml;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class ConditionManager {
+
+ private static final String TAG = "ConditionManager";
+
+ private static final boolean DEBUG = true;
+
+ private static final String FILE_NAME = "condition_state.xml";
+ private static final String TAG_CONDITIONS = "conditions";
+ private static final String TAG_CONDITION = "condition";
+ private static final String ATTR_CLASS = "class";
+
+ private static ConditionManager sInstance;
+
+ private final Context mContext;
+ private final ArrayList<Condition> mConditions;
+ private final File mXmlFile;
+
+ private final ArrayList<ConditionListener> mListeners = new ArrayList<>();
+
+ private ConditionManager(Context context) {
+ mContext = context;
+ mConditions = new ArrayList<Condition>();
+ mXmlFile = new File(context.getFilesDir(), FILE_NAME);
+ if (mXmlFile.exists()) {
+ readFromXml();
+ }
+ addMissingConditions();
+ }
+
+ public void refreshAll() {
+ final int N = mConditions.size();
+ for (int i = 0; i < N; i++) {
+ mConditions.get(i).refreshState();
+ }
+ }
+
+ private void readFromXml() {
+ if (DEBUG) Log.d(TAG, "Reading from " + mXmlFile.toString());
+ try {
+ XmlPullParser parser = Xml.newPullParser();
+ FileReader in = new FileReader(mXmlFile);
+ parser.setInput(in);
+ int state = parser.getEventType();
+
+ while (state != XmlPullParser.END_DOCUMENT) {
+ if (TAG_CONDITION.equals(parser.getName())) {
+ int depth = parser.getDepth();
+ String clz = parser.getAttributeValue("", ATTR_CLASS);
+ Condition condition = createCondition(Class.forName(clz));
+ PersistableBundle bundle = PersistableBundle.restoreFromXml(parser);
+ if (DEBUG) Log.d(TAG, "Reading " + clz + " -- " + bundle);
+ condition.restoreState(bundle);
+ mConditions.add(condition);
+ while (parser.getDepth() > depth) {
+ parser.next();
+ }
+ }
+ state = parser.next();
+ }
+ in.close();
+ } catch (XmlPullParserException | IOException | ClassNotFoundException e) {
+ Log.w(TAG, "Problem reading " + FILE_NAME, e);
+ }
+ }
+
+ private void saveToXml() {
+ if (DEBUG) Log.d(TAG, "Writing to " + mXmlFile.toString());
+ try {
+ XmlSerializer serializer = Xml.newSerializer();
+ FileWriter writer = new FileWriter(mXmlFile);
+ serializer.setOutput(writer);
+
+ serializer.startDocument("UTF-8", true);
+ serializer.startTag("", TAG_CONDITIONS);
+
+ final int N = mConditions.size();
+ for (int i = 0; i < N; i++) {
+ serializer.startTag("", TAG_CONDITION);
+ serializer.attribute("", ATTR_CLASS, mConditions.get(i).getClass().getName());
+ PersistableBundle bundle = new PersistableBundle();
+ mConditions.get(i).saveState(bundle);
+ bundle.saveToXml(serializer);
+ serializer.endTag("", TAG_CONDITION);
+ }
+
+ serializer.endTag("", TAG_CONDITIONS);
+ serializer.flush();
+ writer.close();
+ } catch (XmlPullParserException | IOException e) {
+ Log.w(TAG, "Problem writing " + FILE_NAME, e);
+ }
+ }
+
+ private void addMissingConditions() {
+ addIfMissing(AirplaneModeCondition.class);
+ addIfMissing(HotspotCondition.class);
+ addIfMissing(DndCondition.class);
+ addIfMissing(BatterySaverCondition.class);
+ addIfMissing(CellularDataCondition.class);
+ addIfMissing(BackgroundDataCondition.class);
+ }
+
+ private void addIfMissing(Class<? extends Condition> clz) {
+ if (getCondition(clz) == null) {
+ if (DEBUG) Log.d(TAG, "Adding missing " + clz.getName());
+ mConditions.add(createCondition(clz));
+ }
+ }
+
+ private Condition createCondition(Class<?> clz) {
+ if (AirplaneModeCondition.class == clz) {
+ return new AirplaneModeCondition(this);
+ } else if (HotspotCondition.class == clz) {
+ return new HotspotCondition(this);
+ } else if (DndCondition.class == clz) {
+ return new DndCondition(this);
+ } else if (BatterySaverCondition.class == clz) {
+ return new BatterySaverCondition(this);
+ } else if (CellularDataCondition.class == clz) {
+ return new CellularDataCondition(this);
+ } else if (BackgroundDataCondition.class == clz) {
+ return new BackgroundDataCondition(this);
+ }
+ throw new RuntimeException("Unexpected Condition " + clz);
+ }
+
+ Context getContext() {
+ return mContext;
+ }
+
+ public <T extends Condition> T getCondition(Class<T> clz) {
+ final int N = mConditions.size();
+ for (int i = 0; i < N; i++) {
+ if (clz.equals(mConditions.get(i).getClass())) {
+ return (T) mConditions.get(i);
+ }
+ }
+ return null;
+ }
+
+ public List<Condition> getConditions() {
+ return mConditions;
+ }
+
+ public List<Condition> getVisibleConditions() {
+ List<Condition> conditions = new ArrayList<>();
+ final int N = mConditions.size();
+ for (int i = 0; i < N; i++) {
+ if (mConditions.get(i).shouldShow()) {
+ conditions.add(mConditions.get(i));
+ }
+ }
+ Collections.sort(conditions, CONDITION_COMPARATOR);
+ return conditions;
+ }
+
+ public void notifyChanged(Condition condition) {
+ saveToXml();
+ final int N = mListeners.size();
+ for (int i = 0; i < N; i++) {
+ mListeners.get(i).onConditionsChanged();
+ }
+ }
+
+ public void addListener(ConditionListener listener) {
+ mListeners.add(listener);
+ }
+
+ public void remListener(ConditionListener listener) {
+ mListeners.remove(listener);
+ }
+
+ public static ConditionManager get(Context context) {
+ if (sInstance == null) {
+ sInstance = new ConditionManager(context);
+ }
+ return sInstance;
+ }
+
+ public interface ConditionListener {
+ void onConditionsChanged();
+ }
+
+ private static final Comparator<Condition> CONDITION_COMPARATOR = new Comparator<Condition>() {
+ @Override
+ public int compare(Condition lhs, Condition rhs) {
+ return Long.compare(lhs.getLastChange(), rhs.getLastChange());
+ }
+ };
+}
diff --git a/src/com/android/settings/dashboard/conditional/DndCondition.java b/src/com/android/settings/dashboard/conditional/DndCondition.java
new file mode 100644
index 0000000..38f5ef1
--- /dev/null
+++ b/src/com/android/settings/dashboard/conditional/DndCondition.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2015 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.dashboard.conditional;
+
+import android.app.ActivityManager;
+import android.app.NotificationManager;
+import android.app.StatusBarManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.provider.Settings;
+import android.service.notification.ZenModeConfig;
+import com.android.settings.R;
+
+public class DndCondition extends Condition {
+
+ private static final String TAG = "DndCondition";
+
+ private int mZen;
+ private ZenModeConfig mConfig;
+
+ public DndCondition(ConditionManager manager) {
+ super(manager);
+ }
+
+ @Override
+ public void refreshState() {
+ NotificationManager notificationManager =
+ mManager.getContext().getSystemService(NotificationManager.class);
+ mZen = notificationManager.getZenMode();
+ boolean zenModeEnabled = mZen != Settings.Global.ZEN_MODE_OFF;
+ if (zenModeEnabled) {
+ mConfig = notificationManager.getZenModeConfig();
+ } else {
+ mConfig = null;
+ }
+ setActive(zenModeEnabled);
+ }
+
+ @Override
+ protected Class<?> getReceiverClass() {
+ return Receiver.class;
+ }
+
+ private CharSequence getZenState() {
+ switch (mZen) {
+ case Settings.Global.ZEN_MODE_ALARMS:
+ return mManager.getContext().getString(R.string.zen_mode_option_alarms);
+ case Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
+ return mManager.getContext().getString(
+ R.string.zen_mode_option_important_interruptions);
+ case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
+ return mManager.getContext().getString(R.string.zen_mode_option_no_interruptions);
+ }
+ return null;
+ }
+
+ @Override
+ public Icon getIcon() {
+ return Icon.createWithResource(mManager.getContext(), R.drawable.ic_zen);
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return mManager.getContext().getString(R.string.condition_zen_title, getZenState());
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ final boolean isForever = mConfig != null && mConfig.manualRule != null
+ && mConfig.manualRule.conditionId == null;
+ return isForever ? mManager.getContext().getString(com.android.internal.R.string.zen_mode_forever_dnd)
+ : ZenModeConfig.getConditionSummary(mManager.getContext(), mConfig,
+ ActivityManager.getCurrentUser(),
+ false);
+ }
+
+ @Override
+ public CharSequence[] getActions() {
+ return new CharSequence[] { mManager.getContext().getString(R.string.condition_turn_off) };
+ }
+
+ @Override
+ public void onPrimaryClick() {
+ StatusBarManager statusBar = mManager.getContext().getSystemService(StatusBarManager.class);
+ statusBar.expandSettingsPanel("dnd");
+ }
+
+ @Override
+ public void onActionClick(int index) {
+ if (index == 0) {
+ NotificationManager notificationManager = mManager.getContext().getSystemService(
+ NotificationManager.class);
+ notificationManager.setZenMode(Settings.Global.ZEN_MODE_OFF, null, TAG);
+ setActive(false);
+ } else {
+ throw new IllegalArgumentException("Unexpected index " + index);
+ }
+ }
+
+ public static class Receiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED_INTERNAL
+ .equals(intent.getAction())) {
+ ConditionManager.get(context).getCondition(DndCondition.class)
+ .refreshState();
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/dashboard/conditional/FocusRecyclerView.java b/src/com/android/settings/dashboard/conditional/FocusRecyclerView.java
new file mode 100644
index 0000000..af51ed5
--- /dev/null
+++ b/src/com/android/settings/dashboard/conditional/FocusRecyclerView.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2015, 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.dashboard.conditional;
+
+import android.content.Context;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.RecyclerView;
+import android.util.AttributeSet;
+
+/**
+ * Version of RecyclerView that can have listeners for onWindowFocusChanged.
+ */
+public class FocusRecyclerView extends RecyclerView {
+
+ private FocusListener mListener;
+
+ public FocusRecyclerView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ super.onWindowFocusChanged(hasWindowFocus);
+ if (mListener != null) {
+ mListener.onWindowFocusChanged(hasWindowFocus);
+ }
+ }
+
+ public void setListener(FocusListener listener) {
+ mListener = listener;
+ }
+
+ public interface FocusListener {
+ void onWindowFocusChanged(boolean hasWindowFocus);
+ }
+}
diff --git a/src/com/android/settings/dashboard/conditional/HotspotCondition.java b/src/com/android/settings/dashboard/conditional/HotspotCondition.java
new file mode 100644
index 0000000..71e79c4
--- /dev/null
+++ b/src/com/android/settings/dashboard/conditional/HotspotCondition.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2015 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.dashboard.conditional;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import com.android.settings.R;
+import com.android.settings.TetherSettings;
+import com.android.settings.Utils;
+import com.android.settingslib.TetherUtil;
+
+public class HotspotCondition extends Condition {
+
+ private final WifiManager mWifiManager;
+
+ public HotspotCondition(ConditionManager manager) {
+ super(manager);
+ mWifiManager = mManager.getContext().getSystemService(WifiManager.class);
+ }
+
+ @Override
+ public void refreshState() {
+ boolean wifiTetherEnabled = TetherUtil.isWifiTetherEnabled(mManager.getContext());
+ setActive(wifiTetherEnabled);
+ }
+
+ @Override
+ protected Class<?> getReceiverClass() {
+ return Receiver.class;
+ }
+
+ @Override
+ public Icon getIcon() {
+ return Icon.createWithResource(mManager.getContext(), R.drawable.ic_hotspot);
+ }
+
+ private String getSsid() {
+ WifiConfiguration wifiConfig = mWifiManager.getWifiApConfiguration();
+ if (wifiConfig == null) {
+ return mManager.getContext().getString(
+ com.android.internal.R.string.wifi_tether_configure_ssid_default);
+ } else {
+ return wifiConfig.SSID;
+ }
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return mManager.getContext().getString(R.string.condition_hotspot_title);
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return mManager.getContext().getString(R.string.condition_hotspot_summary, getSsid());
+ }
+
+ @Override
+ public CharSequence[] getActions() {
+ return new CharSequence[] { mManager.getContext().getString(R.string.condition_turn_off) };
+ }
+
+ @Override
+ public void onPrimaryClick() {
+ Utils.startWithFragment(mManager.getContext(), TetherSettings.class.getName(), null, null,
+ 0, R.string.tether_settings_title_all, null);
+ }
+
+ @Override
+ public void onActionClick(int index) {
+ if (index == 0) {
+ TetherUtil.setWifiTethering(false, mManager.getContext());
+ setActive(false);
+ } else {
+ throw new IllegalArgumentException("Unexpected index " + index);
+ }
+ }
+
+ public static class Receiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (WifiManager.WIFI_AP_STATE_CHANGED_ACTION.equals(intent.getAction())) {
+ ConditionManager.get(context).getCondition(HotspotCondition.class)
+ .refreshState();
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/display/DisplayDensityUtils.java b/src/com/android/settings/display/DisplayDensityUtils.java
new file mode 100644
index 0000000..cef5418
--- /dev/null
+++ b/src/com/android/settings/display/DisplayDensityUtils.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2015 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.display;
+
+import com.android.settings.R;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.AsyncTask;
+import android.os.RemoteException;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.MathUtils;
+import android.view.Display;
+import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
+
+import java.util.Arrays;
+
+/**
+ * Utility methods for working with display density.
+ */
+class DisplayDensityUtils {
+ private static final String LOG_TAG = "DisplayDensityUtils";
+
+ /** Minimum increment between density scales. */
+ private static final float MIN_SCALE_INTERVAL = 0.09f;
+
+ /** Minimum density scale. This is available on all devices. */
+ private static final float MIN_SCALE = 0.85f;
+
+ /** Maximum density scale. The actual scale used depends on the device. */
+ private static final float MAX_SCALE = 1.50f;
+
+ /** Summary used for "normal" scale. */
+ private static final int SUMMARY_NORMAL = R.string.screen_zoom_summary_normal;
+
+ /** Summary used for "custom" scale. */
+ private static final int SUMMARY_CUSTOM = R.string.screen_zoom_summary_custom;
+
+ /**
+ * Summaries for scales smaller than "normal" in order of smallest to
+ * largest.
+ */
+ private static final int[] SUMMARIES_SMALLER = new int[] {
+ R.string.screen_zoom_summary_small
+ };
+
+ /**
+ * Summaries for scales larger than "normal" in order of smallest to
+ * largest.
+ */
+ private static final int[] SUMMARIES_LARGER = new int[] {
+ R.string.screen_zoom_summary_large,
+ R.string.screen_zoom_summary_very_large,
+ R.string.screen_zoom_summary_extremely_large,
+ };
+
+ /**
+ * Minimum allowed screen dimension, corresponds to resource qualifiers
+ * "small" or "sw320dp". This value must be at least the minimum screen
+ * size required by the CDD so that we meet developer expectations.
+ */
+ private static final int MIN_DIMENSION_DP = 320;
+
+ private final String[] mEntries;
+ private final int[] mValues;
+
+ private final int mNormalDensity;
+ private final int mCurrentIndex;
+
+ public DisplayDensityUtils(Context context) {
+ final int normalDensity = DisplayDensityUtils.getNormalDisplayDensity(
+ Display.DEFAULT_DISPLAY);
+ if (normalDensity <= 0) {
+ mEntries = null;
+ mValues = null;
+ mNormalDensity = 0;
+ mCurrentIndex = -1;
+ return;
+ }
+
+ final Resources res = context.getResources();
+ final DisplayMetrics metrics = res.getDisplayMetrics();
+ final int currentDensity = metrics.densityDpi;
+ int currentDensityIndex = -1;
+
+ // Compute number of "larger" and "smaller" scales for this display.
+ final int minDimensionPx = Math.min(metrics.widthPixels, metrics.heightPixels);
+ final int maxDensity = DisplayMetrics.DENSITY_MEDIUM * minDimensionPx / MIN_DIMENSION_DP;
+ final float maxScale = Math.min(MAX_SCALE, maxDensity / (float) normalDensity);
+ final float minScale = MIN_SCALE;
+ final int numLarger = (int) MathUtils.constrain((maxScale - 1) / MIN_SCALE_INTERVAL,
+ 0, SUMMARIES_LARGER.length);
+ final int numSmaller = (int) MathUtils.constrain((1 - minScale) / MIN_SCALE_INTERVAL,
+ 0, SUMMARIES_SMALLER.length);
+
+ String[] entries = new String[1 + numSmaller + numLarger];
+ int[] values = new int[entries.length];
+ int curIndex = 0;
+
+ if (numSmaller > 0) {
+ final float interval = (1 - minScale) / numSmaller;
+ for (int i = numSmaller - 1; i >= 0; i--) {
+ final int density = (int) (normalDensity * (1 - (i + 1) * interval));
+ if (currentDensity == density) {
+ currentDensityIndex = curIndex;
+ }
+ entries[curIndex] = res.getString(SUMMARIES_SMALLER[i]);
+ values[curIndex] = density;
+ curIndex++;
+ }
+ }
+
+ if (currentDensity == normalDensity) {
+ currentDensityIndex = curIndex;
+ }
+ values[curIndex] = normalDensity;
+ entries[curIndex] = res.getString(SUMMARY_NORMAL);
+ curIndex++;
+
+ if (numLarger > 0) {
+ final float interval = (maxScale - 1) / numLarger;
+ for (int i = 0; i < numLarger; i++) {
+ final int density = (int) (normalDensity * (1 + (i + 1) * interval));
+ if (currentDensity == density) {
+ currentDensityIndex = curIndex;
+ }
+ values[curIndex] = density;
+ entries[curIndex] = res.getString(SUMMARIES_LARGER[i]);
+ curIndex++;
+ }
+ }
+
+ final int displayIndex;
+ if (currentDensityIndex >= 0) {
+ displayIndex = currentDensityIndex;
+ } else {
+ // We don't understand the current density. Must have been set by
+ // someone else. Make room for another entry...
+ values = Arrays.copyOf(values, values.length + 1);
+ values[curIndex] = currentDensity;
+
+ entries = Arrays.copyOf(entries, values.length + 1);
+ entries[curIndex] = res.getString(SUMMARY_CUSTOM, currentDensity);
+
+ displayIndex = curIndex;
+ }
+
+ mNormalDensity = normalDensity;
+ mCurrentIndex = displayIndex;
+ mEntries = entries;
+ mValues = values;
+ }
+
+ public String[] getEntries() {
+ return mEntries;
+ }
+
+ public int[] getValues() {
+ return mValues;
+ }
+
+ public int getCurrentIndex() {
+ return mCurrentIndex;
+ }
+
+ public int getNormalDensity() {
+ return mNormalDensity;
+ }
+
+ /**
+ * Returns the normal (default) density for the specified display.
+ *
+ * @param displayId the identifier of the display
+ * @return the normal density of the specified display, or {@code -1} if
+ * the display does not exist or the density could not be obtained
+ */
+ private static int getNormalDisplayDensity(int displayId) {
+ try {
+ final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+ return wm.getInitialDisplayDensity(displayId);
+ } catch (RemoteException exc) {
+ return -1;
+ }
+ }
+
+ /**
+ * Asynchronously applies display density changes to the specified display.
+ *
+ * @param displayId the identifier of the display to modify
+ */
+ public static void clearForcedDisplayDensity(final int displayId) {
+ AsyncTask.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+ wm.clearForcedDisplayDensity(displayId);
+ } catch (RemoteException exc) {
+ Log.w(LOG_TAG, "Unable to clear forced display density setting");
+ }
+ }
+ });
+ }
+
+ /**
+ * Asynchronously applies display density changes to the specified display.
+ *
+ * @param displayId the identifier of the display to modify
+ * @param density the density to force for the specified display
+ */
+ public static void setForcedDisplayDensity(final int displayId, final int density) {
+ AsyncTask.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+ wm.setForcedDisplayDensity(displayId, density);
+ } catch (RemoteException exc) {
+ Log.w(LOG_TAG, "Unable to save forced display density setting");
+ }
+ }
+ });
+ }
+}
diff --git a/src/com/android/settings/display/ScreenZoomPreference.java b/src/com/android/settings/display/ScreenZoomPreference.java
new file mode 100644
index 0000000..78cc49c
--- /dev/null
+++ b/src/com/android/settings/display/ScreenZoomPreference.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 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.display;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.v4.content.res.TypedArrayUtils;
+import android.support.v7.preference.PreferenceGroup;
+import android.util.AttributeSet;
+
+/**
+ * Preference for changing the density of the display on which the preference
+ * is visible.
+ */
+public class ScreenZoomPreference extends PreferenceGroup {
+ public ScreenZoomPreference(Context context, AttributeSet attrs) {
+ super(context, attrs, TypedArrayUtils.getAttr(context,
+ android.support.v7.preference.R.attr.preferenceScreenStyle,
+ android.R.attr.preferenceScreenStyle));
+
+ setFragment("com.android.settings.display.ScreenZoomSettings");
+
+ final DisplayDensityUtils density = new DisplayDensityUtils(context);
+ final int defaultIndex = density.getCurrentIndex();
+ if (defaultIndex < 0) {
+ setVisible(false);
+ setEnabled(false);
+ } else {
+ final String[] entries = density.getEntries();
+ final int currentIndex = density.getCurrentIndex();
+ setSummary(entries[currentIndex]);
+ }
+ }
+
+ @Override
+ protected boolean isOnSameScreenAsChildren() {
+ return false;
+ }
+}
diff --git a/src/com/android/settings/display/ScreenZoomSettings.java b/src/com/android/settings/display/ScreenZoomSettings.java
new file mode 100644
index 0000000..1ddcaab
--- /dev/null
+++ b/src/com/android/settings/display/ScreenZoomSettings.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2015 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.display;
+
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settings.search.SearchIndexableRaw;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.view.Display;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.widget.FrameLayout;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Preference fragment used to control screen zoom.
+ */
+public class ScreenZoomSettings extends SettingsPreferenceFragment implements Indexable {
+ /** Duration to use when cross-fading between previews. */
+ private static final long CROSS_FADE_DURATION_MS = 400;
+
+ /** Interpolator to use when cross-fading between previews. */
+ private static final Interpolator FADE_IN_INTERPOLATOR = new DecelerateInterpolator();
+
+ /** Interpolator to use when cross-fading between previews. */
+ private static final Interpolator FADE_OUT_INTERPOLATOR = new AccelerateInterpolator();
+
+ private ViewGroup mPreviewFrame;
+ private TextView mLabel;
+ private View mLarger;
+ private View mSmaller;
+
+ private String[] mEntries;
+ private int[] mValues;
+ private int mNormalDensity;
+ private int mInitialIndex;
+
+ private int mCurrentIndex;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final DisplayDensityUtils density = new DisplayDensityUtils(getContext());
+
+ final int initialIndex = density.getCurrentIndex();
+ if (initialIndex < 0) {
+ // Failed to obtain normal density, which means we failed to
+ // connect to the window manager service. Just use the current
+ // density and don't let the user change anything.
+ final int densityDpi = getResources().getDisplayMetrics().densityDpi;
+ mValues = new int[] { densityDpi };
+ mEntries = new String[] { getString(R.string.screen_zoom_summary_normal) };
+ mInitialIndex = 0;
+ mNormalDensity = densityDpi;
+ } else {
+ mValues = density.getValues();
+ mEntries = density.getEntries();
+ mInitialIndex = initialIndex;
+ mNormalDensity = density.getNormalDensity();
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ final View root = super.onCreateView(inflater, container, savedInstanceState);
+ final ViewGroup list_container = (ViewGroup) root.findViewById(android.R.id.list_container);
+ list_container.removeAllViews();
+
+ final View content = inflater.inflate(R.layout.screen_zoom_activity, list_container, false);
+ list_container.addView(content);
+
+ mLabel = (TextView) content.findViewById(R.id.current_density);
+
+ // The maximum SeekBar value always needs to be non-zero. If there's
+ // only one available zoom level, we'll handle this by disabling the
+ // seek bar.
+ final int max = Math.max(1, mValues.length - 1);
+
+ final SeekBar seekBar = (SeekBar) content.findViewById(R.id.seek_bar);
+ seekBar.setMax(max);
+ seekBar.setProgress(mInitialIndex);
+ seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ setPreviewLayer(progress, true);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {}
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {}
+ });
+
+ mSmaller = content.findViewById(R.id.smaller);
+ mSmaller.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final int progress = seekBar.getProgress();
+ if (progress > 0) {
+ seekBar.setProgress(progress - 1, true);
+ }
+ }
+ });
+
+ mLarger = content.findViewById(R.id.larger);
+ mLarger.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final int progress = seekBar.getProgress();
+ if (progress < seekBar.getMax()) {
+ seekBar.setProgress(progress + 1, true);
+ }
+ }
+ });
+
+ if (mValues.length == 1) {
+ // The larger and smaller buttons will be disabled when we call
+ // setPreviewLayer() later in this method.
+ seekBar.setEnabled(false);
+ }
+
+ mPreviewFrame = (FrameLayout) content.findViewById(R.id.preview_frame);
+
+ // Populate the sample layouts.
+ final Context context = getContext();
+ final Configuration origConfig = context.getResources().getConfiguration();
+ for (int mValue : mValues) {
+ final Configuration config = new Configuration(origConfig);
+ config.densityDpi = mValue;
+
+ // Create a new configuration for the specified density. It won't
+ // have any theme set, so manually apply the current theme.
+ final Context configContext = context.createConfigurationContext(config);
+ configContext.setTheme(context.getThemeResId());
+
+ final LayoutInflater configInflater = LayoutInflater.from(configContext);
+ final View sampleView = configInflater.inflate(
+ R.layout.screen_zoom_preview, mPreviewFrame, false);
+ sampleView.setAlpha(0);
+ sampleView.setVisibility(View.INVISIBLE);
+
+ mPreviewFrame.addView(sampleView);
+ }
+
+ setPreviewLayer(mInitialIndex, false);
+
+ return root;
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+
+ // This will adjust the density SLIGHTLY after the activity has
+ // finished, which could be considered a feature or a bug...
+ commit();
+ }
+
+ private void setPreviewLayer(int index, boolean animate) {
+ mLabel.setText(mEntries[index]);
+
+ if (mCurrentIndex >= 0) {
+ final View lastLayer = mPreviewFrame.getChildAt(mCurrentIndex);
+ if (animate) {
+ lastLayer.animate()
+ .alpha(0)
+ .setInterpolator(FADE_OUT_INTERPOLATOR)
+ .setDuration(CROSS_FADE_DURATION_MS)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ lastLayer.setVisibility(View.INVISIBLE);
+ }
+ });
+ } else {
+ lastLayer.setAlpha(0);
+ lastLayer.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ final View nextLayer = mPreviewFrame.getChildAt(index);
+ if (animate) {
+ nextLayer.animate()
+ .alpha(1)
+ .setInterpolator(FADE_IN_INTERPOLATOR)
+ .setDuration(CROSS_FADE_DURATION_MS)
+ .withStartAction(new Runnable() {
+ @Override
+ public void run() {
+ nextLayer.setVisibility(View.VISIBLE);
+ }
+ });
+ } else {
+ nextLayer.setVisibility(View.VISIBLE);
+ nextLayer.setAlpha(1);
+ }
+
+ mSmaller.setEnabled(index > 0);
+ mLarger.setEnabled(index < mEntries.length - 1);
+
+ mCurrentIndex = index;
+ }
+
+ /**
+ * Persists the selected density and sends a configuration change.
+ */
+ private void commit() {
+ final int densityDpi = mValues[mCurrentIndex];
+ if (densityDpi == mNormalDensity) {
+ DisplayDensityUtils.clearForcedDisplayDensity(Display.DEFAULT_DISPLAY);
+ } else {
+ DisplayDensityUtils.setForcedDisplayDensity(Display.DEFAULT_DISPLAY, densityDpi);
+ }
+ }
+
+ @Override
+ protected int getMetricsCategory() {
+ return InstrumentedFragment.DISPLAY_SCREEN_ZOOM;
+ }
+
+ /** Index provider used to expose this fragment in search. */
+ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
+ final Resources res = context.getResources();
+ final SearchIndexableRaw data = new SearchIndexableRaw(context);
+ data.title = res.getString(R.string.screen_zoom_title);
+ data.screenTitle = res.getString(R.string.screen_zoom_title);
+ data.keywords = res.getString(R.string.screen_zoom_keywords);
+
+ final List<SearchIndexableRaw> result = new ArrayList<>(1);
+ result.add(data);
+ return result;
+ }
+ };
+}
diff --git a/src/com/android/settings/display/TouchBlockingFrameLayout.java b/src/com/android/settings/display/TouchBlockingFrameLayout.java
new file mode 100644
index 0000000..3f5483d
--- /dev/null
+++ b/src/com/android/settings/display/TouchBlockingFrameLayout.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 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.display;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.FrameLayout;
+
+/**
+ * Extension of FrameLayout that consumes all touch events.
+ */
+public class TouchBlockingFrameLayout extends FrameLayout {
+ public TouchBlockingFrameLayout(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ return true;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ return true;
+ }
+}
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
index 63d9335..b246bdf 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollFindSensor.java
@@ -33,7 +33,7 @@
private static final int ENROLLING = 2;
public static final String EXTRA_KEY_LAUNCHED_CONFIRM = "launched_confirm_lock";
- private FingerprintLocationAnimationView mAnimation;
+ private FingerprintFindSensorAnimation mAnimation;
private boolean mLaunchedConfirmLock;
@Override
@@ -46,7 +46,7 @@
if (mToken == null && !mLaunchedConfirmLock) {
launchConfirmLock();
}
- mAnimation = (FingerprintLocationAnimationView) findViewById(
+ mAnimation = (FingerprintFindSensorAnimation) findViewById(
R.id.fingerprint_sensor_location_animation);
}
diff --git a/src/com/android/settings/fingerprint/FingerprintFindSensorAnimation.java b/src/com/android/settings/fingerprint/FingerprintFindSensorAnimation.java
new file mode 100644
index 0000000..cb254ba
--- /dev/null
+++ b/src/com/android/settings/fingerprint/FingerprintFindSensorAnimation.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2015 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.fingerprint;
+
+/**
+ * An abstraction for a view that contains an animation that shows the user
+ * where the fingerprint sensor is on the device.
+ */
+public interface FingerprintFindSensorAnimation {
+
+ /**
+ * Start the animation
+ */
+ void startAnimation();
+
+ /**
+ * Stop the animation
+ */
+ void stopAnimation();
+
+}
diff --git a/src/com/android/settings/fingerprint/FingerprintLocationAnimationVideoView.java b/src/com/android/settings/fingerprint/FingerprintLocationAnimationVideoView.java
new file mode 100644
index 0000000..c1fd2c2
--- /dev/null
+++ b/src/com/android/settings/fingerprint/FingerprintLocationAnimationVideoView.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2015 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.fingerprint;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.SurfaceTexture;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnInfoListener;
+import android.media.MediaPlayer.OnPreparedListener;
+import android.net.Uri;
+import android.util.AttributeSet;
+import android.view.Surface;
+import android.view.TextureView;
+import android.view.View;
+
+import com.android.settings.R;
+
+/**
+ * A view containing a VideoView for showing the user how to enroll a fingerprint
+ */
+public class FingerprintLocationAnimationVideoView extends TextureView
+ implements FingerprintFindSensorAnimation {
+ protected float mAspect = 1.0f; // initial guess until we know
+ protected MediaPlayer mMediaPlayer;
+
+ public FingerprintLocationAnimationVideoView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // Width is driven by measurespec, height is derrived from aspect ratio
+ int originalWidth = MeasureSpec.getSize(widthMeasureSpec);
+ int height = Math.round(mAspect * originalWidth);
+ super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ setSurfaceTextureListener(new SurfaceTextureListener() {
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,
+ int height) {
+ setVisibility(View.INVISIBLE);
+ Uri videoUri = resourceEntryToUri(mContext, R.raw.fingerprint_location_animation);
+ mMediaPlayer = MediaPlayer.create(mContext, videoUri);
+ mMediaPlayer.setSurface(new Surface(surfaceTexture));
+ mMediaPlayer.setOnPreparedListener(new OnPreparedListener() {
+ @Override
+ public void onPrepared(MediaPlayer mediaPlayer) {
+ mediaPlayer.setLooping(true);
+ }
+ });
+ mMediaPlayer.setOnInfoListener(new OnInfoListener() {
+ @Override
+ public boolean onInfo(MediaPlayer mediaPlayer, int what, int extra) {
+ if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
+ // Keep the view hidden until video starts
+ setVisibility(View.VISIBLE);
+ }
+ return false;
+ }
+ });
+ mAspect = (float) mMediaPlayer.getVideoHeight() / mMediaPlayer.getVideoWidth();
+ requestLayout();
+ startAnimation();
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture,
+ int width, int height) {
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
+ return false;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
+ }
+ });
+ }
+
+ private static Uri resourceEntryToUri (Context context, int id) {
+ Resources res = context.getResources();
+ return Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+ res.getResourcePackageName(id) + '/' +
+ res.getResourceTypeName(id) + '/' +
+ res.getResourceEntryName(id));
+ }
+
+ @Override
+ public void startAnimation() {
+ if (mMediaPlayer != null && !mMediaPlayer.isPlaying()) {
+ mMediaPlayer.start();
+ }
+ }
+
+ @Override
+ public void stopAnimation() {
+ if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
+ mMediaPlayer.stop();
+ mMediaPlayer.release();
+ mMediaPlayer = null;
+ }
+ }
+
+}
diff --git a/src/com/android/settings/fingerprint/FingerprintLocationAnimationView.java b/src/com/android/settings/fingerprint/FingerprintLocationAnimationView.java
index 65f38bd..c17069f 100644
--- a/src/com/android/settings/fingerprint/FingerprintLocationAnimationView.java
+++ b/src/com/android/settings/fingerprint/FingerprintLocationAnimationView.java
@@ -34,7 +34,8 @@
/**
* View which plays an animation to indicate where the sensor is on the device.
*/
-public class FingerprintLocationAnimationView extends View {
+public class FingerprintLocationAnimationView extends View implements
+ FingerprintFindSensorAnimation {
private static final float MAX_PULSE_ALPHA = 0.15f;
private static final long DELAY_BETWEEN_PHASE = 1000;
@@ -95,10 +96,12 @@
return getHeight() * mFractionCenterY;
}
+ @Override
public void startAnimation() {
startPhase();
}
+ @Override
public void stopAnimation() {
removeCallbacks(mStartPhaseRunnable);
if (mRadiusAnimator != null) {
diff --git a/src/com/android/settings/fuelgauge/BatterySaverSettings.java b/src/com/android/settings/fuelgauge/BatterySaverSettings.java
index 63ded30..26e7d43 100644
--- a/src/com/android/settings/fuelgauge/BatterySaverSettings.java
+++ b/src/com/android/settings/fuelgauge/BatterySaverSettings.java
@@ -37,6 +37,8 @@
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.widget.SwitchBar;
@@ -144,6 +146,8 @@
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() {
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index 2ed48e9..9974e89 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -17,7 +17,9 @@
package com.android.settings.location;
import android.app.Activity;
+import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -30,6 +32,7 @@
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
+import android.support.v14.preference.SwitchPreference;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
@@ -81,16 +84,10 @@
private static final String TAG = "LocationSettings";
/**
- * Key for managed profile location preference category. Category is shown only
- * if there is a managed profile
+ * Key for managed profile location switch preference. Shown only
+ * if there is a managed profile.
*/
- private static final String KEY_MANAGED_PROFILE_CATEGORY = "managed_profile_location_category";
- /**
- * Key for managed profile location preference. Note it used to be a switch pref and we had to
- * keep the key as strings had been submitted for string freeze before the decision to
- * demote this to a simple preference was made. TODO: Candidate for refactoring.
- */
- private static final String KEY_MANAGED_PROFILE_PREFERENCE = "managed_profile_location_switch";
+ private static final String KEY_MANAGED_PROFILE_SWITCH = "managed_profile_location_switch";
/** Key for preference screen "Mode" */
private static final String KEY_LOCATION_MODE = "location_mode";
/** Key for preference category "Recent location requests" */
@@ -104,7 +101,7 @@
private Switch mSwitch;
private boolean mValidListener = false;
private UserHandle mManagedProfile;
- private Preference mManagedProfilePreference;
+ private SwitchPreference mManagedProfileSwitch;
private Preference mLocationMode;
private PreferenceCategory mCategoryRecentLocationRequests;
/** Receives UPDATE_INTENT */
@@ -250,20 +247,39 @@
mManagedProfile = Utils.getManagedProfile(mUm);
if (mManagedProfile == null) {
// There is no managed profile
- root.removePreference(root.findPreference(KEY_MANAGED_PROFILE_CATEGORY));
- mManagedProfilePreference = null;
+ root.removePreference(root.findPreference(KEY_MANAGED_PROFILE_SWITCH));
+ mManagedProfileSwitch = null;
} else {
- mManagedProfilePreference = root.findPreference(KEY_MANAGED_PROFILE_PREFERENCE);
- mManagedProfilePreference.setOnPreferenceClickListener(null);
+ mManagedProfileSwitch = (SwitchPreference)root
+ .findPreference(KEY_MANAGED_PROFILE_SWITCH);
+ mManagedProfileSwitch.setOnPreferenceClickListener(null);
}
}
- private void changeManagedProfileLocationAccessStatus(boolean enabled, int summaryResId) {
- if (mManagedProfilePreference == null) {
+ private void changeManagedProfileLocationAccessStatus(boolean mainSwitchOn) {
+ if (mManagedProfileSwitch == null) {
return;
}
- mManagedProfilePreference.setEnabled(enabled);
- mManagedProfilePreference.setSummary(summaryResId);
+ boolean enabled = mainSwitchOn;
+ int summaryResId = R.string.switch_off_text;
+ if (mUm.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, mManagedProfile)
+ && getAdminRestrictingManagedProfile() != null) {
+ summaryResId = R.string.managed_profile_location_switch_lockdown;
+ enabled = false;
+ }
+
+ mManagedProfileSwitch.setEnabled(enabled);
+ mManagedProfileSwitch.setOnPreferenceClickListener(null);
+ if (!enabled) {
+ mManagedProfileSwitch.setChecked(false);
+ } else {
+ final boolean isRestricted = isManagedProfileRestrictedByBase();
+ mManagedProfileSwitch.setChecked(!isRestricted);
+ summaryResId = (isRestricted ?
+ R.string.switch_off_text : R.string.switch_on_text);
+ mManagedProfileSwitch.setOnPreferenceClickListener(mManagedProfileSwitchClickListener);
+ }
+ mManagedProfileSwitch.setSummary(summaryResId);
}
/**
@@ -374,18 +390,7 @@
}
}
- if (mManagedProfilePreference != null) {
- if (mUm.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, mManagedProfile)) {
- changeManagedProfileLocationAccessStatus(false,
- R.string.managed_profile_location_switch_lockdown);
- } else {
- if (enabled) {
- changeManagedProfileLocationAccessStatus(true, R.string.switch_on_text);
- } else {
- changeManagedProfileLocationAccessStatus(false, R.string.switch_off_text);
- }
- }
- }
+ changeManagedProfileLocationAccessStatus(enabled);
// As a safety measure, also reloads on location mode change to ensure the settings are
// up-to-date even if an affected app doesn't send the setting changed broadcast.
@@ -404,6 +409,47 @@
}
}
+ private ComponentName getAdminRestrictingManagedProfile() {
+ if (mManagedProfile == null) {
+ return null;
+ }
+ DevicePolicyManager dpm = (DevicePolicyManager)getActivity().getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ if (dpm == null) {
+ return null;
+ }
+ List<ComponentName> admins = dpm.getActiveAdminsAsUser(mManagedProfile.getIdentifier());
+ for (int i = 0; i < admins.size(); ++i) {
+ final ComponentName admin = admins.get(i);
+ Bundle restrictions = dpm.getUserRestrictions(admin, mManagedProfile.getIdentifier());
+ if (restrictions != null && restrictions.getBoolean(UserManager.DISALLOW_SHARE_LOCATION,
+ false)) {
+ return admin;
+ }
+ }
+ return null;
+ }
+
+ private boolean isManagedProfileRestrictedByBase() {
+ if (mManagedProfile == null) {
+ return false;
+ }
+ return mUm.hasBaseUserRestriction(UserManager.DISALLOW_SHARE_LOCATION, mManagedProfile);
+ }
+
+ private Preference.OnPreferenceClickListener mManagedProfileSwitchClickListener =
+ new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ final boolean switchState = mManagedProfileSwitch.isChecked();
+ mUm.setUserRestriction(UserManager.DISALLOW_SHARE_LOCATION,
+ !switchState, mManagedProfile);
+ mManagedProfileSwitch.setSummary(switchState ?
+ R.string.switch_on_text : R.string.switch_off_text);
+ return true;
+ }
+ };
+
private class PackageEntryClickedListener
implements Preference.OnPreferenceClickListener {
private String mPackage;
diff --git a/src/com/android/settings/nfc/NfcForegroundPreference.java b/src/com/android/settings/nfc/NfcForegroundPreference.java
index 2e0c3d8..f2d98bf 100644
--- a/src/com/android/settings/nfc/NfcForegroundPreference.java
+++ b/src/com/android/settings/nfc/NfcForegroundPreference.java
@@ -16,8 +16,8 @@
package com.android.settings.nfc;
import android.content.Context;
+import android.support.v7.preference.DropDownPreference;
-import com.android.settings.DropDownPreference;
import com.android.settings.R;
public class NfcForegroundPreference extends DropDownPreference implements
diff --git a/src/com/android/settings/nfc/PaymentSettings.java b/src/com/android/settings/nfc/PaymentSettings.java
index 42545b9..dc7badf 100644
--- a/src/com/android/settings/nfc/PaymentSettings.java
+++ b/src/com/android/settings/nfc/PaymentSettings.java
@@ -19,6 +19,7 @@
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
+import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.support.v7.preference.PreferenceManager;
import android.support.v7.preference.PreferenceScreen;
@@ -111,12 +112,14 @@
@Override
public void setListening(boolean listening) {
- if (listening) {
+ if (listening && NfcAdapter.getDefaultAdapter(mContext) != null) {
PaymentBackend paymentBackend = new PaymentBackend(mContext);
paymentBackend.refresh();
PaymentAppInfo app = paymentBackend.getDefaultApp();
- mSummaryLoader.setSummary(this, mContext.getString(R.string.payment_summary,
- app.label));
+ if (app != null) {
+ mSummaryLoader.setSummary(this, mContext.getString(R.string.payment_summary,
+ app.label));
+ }
}
}
}
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index deba7d4..2ee2b81 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -28,10 +28,12 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
+import android.service.notification.NotificationListenerService;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
+import android.support.v7.preference.PreferenceCategory;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -55,6 +57,7 @@
private static final String KEY_BLOCK = "block";
private static final String KEY_APP_SETTINGS = "app_settings";
+ private static final String KEY_CATEGORIES = "categories";
private static final Intent APP_NOTIFICATION_PREFS_CATEGORY_INTENT
= new Intent(Intent.ACTION_MAIN)
@@ -64,6 +67,7 @@
private Context mContext;
private SwitchPreference mBlock;
+ private PreferenceCategory mCategories;
private AppRow mAppRow;
private boolean mCreated;
private boolean mIsSystemPackage;
@@ -136,6 +140,7 @@
// Add topics
List<Notification.Topic> topics = mBackend.getTopics(pkg, mUid);
+ mCategories = (PreferenceCategory) getPreferenceScreen().findPreference(KEY_CATEGORIES);
for (Notification.Topic topic : topics) {
Preference topicPreference = new Preference(mContext);
topicPreference.setKey(topic.getId());
@@ -151,8 +156,7 @@
TopicNotificationSettings.class.getName(),
topicArgs, null, R.string.topic_notifications_title, null, false);
topicPreference.setIntent(topicIntent);
- // Add preference to the settings menu.
- getPreferenceScreen().addPreference(topicPreference);
+ mCategories.addPreference(topicPreference);
}
mBlock.setChecked(mAppRow.banned);
@@ -198,6 +202,9 @@
private void updateDependents(boolean banned) {
setVisible(mBlock, !mIsSystemPackage);
+ if (mCategories != null) {
+ setVisible(mCategories, !banned);
+ }
}
private void setVisible(Preference p, boolean visible) {
diff --git a/src/com/android/settings/notification/ConfigureNotificationSettings.java b/src/com/android/settings/notification/ConfigureNotificationSettings.java
index 4b438f0..f3f74a7 100644
--- a/src/com/android/settings/notification/ConfigureNotificationSettings.java
+++ b/src/com/android/settings/notification/ConfigureNotificationSettings.java
@@ -17,7 +17,6 @@
package com.android.settings.notification;
import com.android.internal.widget.LockPatternUtils;
-import com.android.settings.DropDownPreference;
import com.android.settings.InstrumentedFragment;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
@@ -31,6 +30,7 @@
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
+import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.TwoStatePreference;
diff --git a/src/com/android/settings/notification/ImportanceSeekBarPreference.java b/src/com/android/settings/notification/ImportanceSeekBarPreference.java
new file mode 100644
index 0000000..58892e3
--- /dev/null
+++ b/src/com/android/settings/notification/ImportanceSeekBarPreference.java
@@ -0,0 +1,110 @@
+/**
+ * Copyright (C) 2015 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 com.android.settings.R;
+import com.android.settings.SeekBarPreference;
+
+import android.content.Context;
+import android.service.notification.NotificationListenerService;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.util.AttributeSet;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+/**
+ * A slider preference that controls notification importance.
+ **/
+public class ImportanceSeekBarPreference extends SeekBarPreference implements
+ SeekBar.OnSeekBarChangeListener {
+ private static final String TAG = "ImportanceSeekBarPref";
+
+ private Callback mCallback;
+ private TextView mSummaryTextView;
+ private String mSummary;
+
+ public ImportanceSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ setLayoutResource(R.layout.preference_importance_slider);
+ }
+
+ public ImportanceSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public ImportanceSeekBarPreference(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ImportanceSeekBarPreference(Context context) {
+ this(context, null);
+ }
+
+ public void setCallback(Callback callback) {
+ mCallback = callback;
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder view) {
+ super.onBindViewHolder(view);
+ mSummaryTextView = (TextView) view.findViewById(com.android.internal.R.id.summary);
+ }
+
+ @Override
+ public void setProgress(int progress) {
+ mSummary = getProgressSummary(progress);
+ super.setProgress(progress);
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, final int progress, boolean fromTouch) {
+ super.onProgressChanged(seekBar, progress, fromTouch);
+ if (mSummaryTextView != null) {
+ mSummaryTextView.setText(getProgressSummary(progress));
+ }
+ if (fromTouch) {
+ mCallback.onImportanceChanged(progress);
+ }
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return mSummary;
+ }
+
+ private String getProgressSummary(int progress) {
+ switch (progress) {
+ case NotificationListenerService.Ranking.IMPORTANCE_NONE:
+ return getContext().getString(R.string.notification_importance_blocked);
+ case NotificationListenerService.Ranking.IMPORTANCE_LOW:
+ return getContext().getString(R.string.notification_importance_low);
+ case NotificationListenerService.Ranking.IMPORTANCE_DEFAULT:
+ return getContext().getString(R.string.notification_importance_default);
+ case NotificationListenerService.Ranking.IMPORTANCE_HIGH:
+ return getContext().getString(R.string.notification_importance_high);
+ case NotificationListenerService.Ranking.IMPORTANCE_MAX:
+ return getContext().getString(R.string.notification_importance_max);
+ default:
+ return "";
+ }
+ }
+
+ public interface Callback {
+ void onImportanceChanged(int progress);
+ }
+}
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
index dcebf8b..15f82fe 100644
--- a/src/com/android/settings/notification/NotificationBackend.java
+++ b/src/com/android/settings/notification/NotificationBackend.java
@@ -62,6 +62,7 @@
row.priority = getBypassZenMode(row.pkg, row.uid, row.topic);
row.sensitive = getSensitive(row.pkg, row.uid, row.topic);
row.banned = getNotificationsBanned(row.pkg, row.uid);
+ row.importance = getImportance(row.pkg, row.uid, row.topic);
return row;
}
@@ -128,6 +129,25 @@
}
}
+ public boolean setImportance(String pkg, int uid, Notification.Topic topic, int importance) {
+ try {
+ sINM.setTopicImportance(pkg, uid, topic, importance);
+ return true;
+ } catch (Exception e) {
+ Log.w(TAG, "Error calling NoMan", e);
+ return false;
+ }
+ }
+
+ public int getImportance(String pkg, int uid, Notification.Topic topic) {
+ try {
+ return sINM.getTopicImportance(pkg, uid, topic);
+ } catch (Exception e) {
+ Log.w(TAG, "Error calling NoMan", e);
+ return NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+ }
+ }
+
public List<Notification.Topic> getTopics(String pkg, int uid) {
try {
final ParceledListSlice<Notification.Topic> parceledList = sINM.getTopics(pkg, uid);
@@ -156,6 +176,7 @@
public Notification.Topic topic;
public boolean priority;
public boolean sensitive;
+ public int importance;
}
}
diff --git a/src/com/android/settings/notification/SettingPref.java b/src/com/android/settings/notification/SettingPref.java
index 99ce3b5..18efc33 100644
--- a/src/com/android/settings/notification/SettingPref.java
+++ b/src/com/android/settings/notification/SettingPref.java
@@ -22,11 +22,11 @@
import android.net.Uri;
import android.provider.Settings.Global;
import android.provider.Settings.System;
+import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.TwoStatePreference;
-import com.android.settings.DropDownPreference;
import com.android.settings.SettingsPreferenceFragment;
/** Helper to manage a two-state or dropdown preference bound to a global or system setting. */
diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java
index 9e27528..11517ea 100644
--- a/src/com/android/settings/notification/SoundSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -76,6 +76,7 @@
private static final String KEY_VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
private static final String KEY_WIFI_DISPLAY = "wifi_display";
private static final String KEY_ZEN_MODE = "zen_mode";
+ private static final String KEY_CELL_BROADCAST_SETTINGS = "cell_broadcast_settings";
private static final String[] RESTRICTED_KEYS = {
KEY_MEDIA_VOLUME,
@@ -105,6 +106,7 @@
private ComponentName mSuppressor;
private int mRingerMode = -1;
+ private PackageManager mPm;
private UserManager mUserManager;
private RingtonePreference mRequestPreference;
@@ -117,6 +119,7 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = getActivity();
+ mPm = getPackageManager();
mUserManager = UserManager.get(getContext());
mVoiceCapable = Utils.isVoiceCapable(mContext);
@@ -143,6 +146,24 @@
com.android.internal.R.drawable.ic_audio_ring_notif_mute);
removePreference(KEY_RING_VOLUME);
}
+
+ // Enable link to CMAS app settings depending on the value in config.xml.
+ boolean isCellBroadcastAppLinkEnabled = this.getResources().getBoolean(
+ com.android.internal.R.bool.config_cellBroadcastAppLinks);
+ try {
+ if (isCellBroadcastAppLinkEnabled) {
+ if (mPm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
+ == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
+ isCellBroadcastAppLinkEnabled = false; // CMAS app disabled
+ }
+ }
+ } catch (IllegalArgumentException ignored) {
+ isCellBroadcastAppLinkEnabled = false; // CMAS app not installed
+ }
+ if (!mUserManager.isAdminUser() || !isCellBroadcastAppLinkEnabled
+ || mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS)) {
+ removePreference(KEY_CELL_BROADCAST_SETTINGS);
+ }
initRingtones();
initVibrateWhenRinging();
updateRingerMode();
@@ -545,7 +566,7 @@
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
- sir.xmlResId = R.xml.configure_notification_settings;
+ sir.xmlResId = R.xml.sound_settings;
return Arrays.asList(sir);
}
@@ -559,6 +580,27 @@
rt.add(KEY_WIFI_DISPLAY);
rt.add(KEY_VIBRATE_WHEN_RINGING);
}
+
+ final PackageManager pm = context.getPackageManager();
+ final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+
+ // Enable link to CMAS app settings depending on the value in config.xml.
+ boolean isCellBroadcastAppLinkEnabled = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_cellBroadcastAppLinks);
+ try {
+ if (isCellBroadcastAppLinkEnabled) {
+ if (pm.getApplicationEnabledSetting("com.android.cellbroadcastreceiver")
+ == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
+ isCellBroadcastAppLinkEnabled = false; // CMAS app disabled
+ }
+ }
+ } catch (IllegalArgumentException ignored) {
+ isCellBroadcastAppLinkEnabled = false; // CMAS app not installed
+ }
+ if (!um.isAdminUser() || !isCellBroadcastAppLinkEnabled) {
+ rt.add(KEY_CELL_BROADCAST_SETTINGS);
+ }
+
return rt;
}
};
diff --git a/src/com/android/settings/notification/TopicNotificationSettings.java b/src/com/android/settings/notification/TopicNotificationSettings.java
index 48c611e..e8586c2 100644
--- a/src/com/android/settings/notification/TopicNotificationSettings.java
+++ b/src/com/android/settings/notification/TopicNotificationSettings.java
@@ -21,23 +21,22 @@
import com.android.settings.AppHeader;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.Utils;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.notification.NotificationBackend.TopicRow;
import android.app.Notification;
+import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
+import android.service.notification.NotificationListenerService;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
-import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
@@ -50,16 +49,18 @@
protected static final String ARG_PACKAGE_INFO = "arg_info";
private static final String KEY_BYPASS_DND = "bypass_dnd";
private static final String KEY_SENSITIVE = "sensitive";
+ private static final String KEY_IMPORTANCE = "importance";
private final NotificationBackend mBackend = new NotificationBackend();
private Context mContext;
+ private ImportanceSeekBarPreference mImportance;
private SwitchPreference mPriority;
private SwitchPreference mSensitive;
private TopicRow mTopicRow;
private boolean mCreated;
- private boolean mIsSystemPackage;
private int mUid;
+ private boolean mDndVisualEffectsSuppressed;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
@@ -93,6 +94,10 @@
return;
}
+ NotificationManager.Policy policy =
+ NotificationManager.from(mContext).getNotificationPolicy();
+ mDndVisualEffectsSuppressed = policy == null ? false : policy.suppressedVisualEffects != 0;
+
final Notification.Topic topic = args != null && args.containsKey(ARG_TOPIC)
? (Notification.Topic) args.getParcelable(ARG_TOPIC) : null;
@@ -119,14 +124,28 @@
}
final PackageManager pm = getPackageManager();
- mIsSystemPackage = Utils.isSystemPackage(pm, info);
addPreferencesFromResource(R.xml.topic_notification_settings);
+ mImportance = (ImportanceSeekBarPreference) findPreference(KEY_IMPORTANCE);
mPriority = (SwitchPreference) findPreference(KEY_BYPASS_DND);
mSensitive = (SwitchPreference) findPreference(KEY_SENSITIVE);
mTopicRow = mBackend.loadTopicRow(pm, info.applicationInfo, topic);
+ mImportance.setMax(4);
+ // TODO: stop defaulting to 'normal' in the UI when there are mocks for this scenario.
+ int importance =
+ mTopicRow.importance == NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED
+ ? NotificationListenerService.Ranking.IMPORTANCE_DEFAULT
+ : mTopicRow.importance;
+ mImportance.setProgress(importance);
+ mImportance.setCallback(new ImportanceSeekBarPreference.Callback() {
+ @Override
+ public void onImportanceChanged(int progress) {
+ mBackend.setImportance(mTopicRow.pkg, mTopicRow.uid, mTopicRow.topic, progress);
+ updateDependents(progress);
+ }
+ });
mPriority.setChecked(mTopicRow.priority);
mSensitive.setChecked(mTopicRow.sensitive);
@@ -145,7 +164,7 @@
return mBackend.setSensitive(info.packageName, mUid, topic, sensitive);
}
});
- updateDependents(mTopicRow.banned);
+ updateDependents(mTopicRow.importance);
}
@@ -158,15 +177,17 @@
}
}
- private void updateDependents(boolean banned) {
+ private void updateDependents(int importance) {
final boolean lockscreenSecure = new LockPatternUtils(getActivity()).isSecure(
UserHandle.myUserId());
final boolean lockscreenNotificationsEnabled = getLockscreenNotificationsEnabled();
final boolean allowPrivate = getLockscreenAllowPrivateNotifications();
- setVisible(mPriority, mIsSystemPackage || !banned);
- setVisible(mSensitive, mIsSystemPackage || !banned && lockscreenSecure
- && lockscreenNotificationsEnabled && allowPrivate);
+
+ setVisible(mPriority, importance > NotificationListenerService.Ranking.IMPORTANCE_DEFAULT
+ && !mDndVisualEffectsSuppressed);
+ setVisible(mSensitive, (importance > NotificationListenerService.Ranking.IMPORTANCE_LOW)
+ && lockscreenSecure && lockscreenNotificationsEnabled && allowPrivate);
}
private void setVisible(Preference p, boolean visible) {
diff --git a/src/com/android/settings/notification/ZenAccessSettings.java b/src/com/android/settings/notification/ZenAccessSettings.java
index 1c85f4d..4cec0b4 100644
--- a/src/com/android/settings/notification/ZenAccessSettings.java
+++ b/src/com/android/settings/notification/ZenAccessSettings.java
@@ -119,15 +119,15 @@
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean access = (Boolean) newValue;
- if (!access) {
- // disabling access
- setAccess(mContext, pkg, access);
- return true;
+ if (access) {
+ new ScaryWarningDialogFragment()
+ .setPkgInfo(pkg, label)
+ .show(getFragmentManager(), "dialog");
+ } else {
+ new FriendlyWarningDialogFragment()
+ .setPkgInfo(pkg, label)
+ .show(getFragmentManager(), "dialog");
}
- // enabling access: show a scary dialog first
- new ScaryWarningDialogFragment()
- .setPkgInfo(pkg, label)
- .show(getFragmentManager(), "dialog");
return false;
}
});
@@ -149,6 +149,16 @@
});
}
+ private static void deleteRules(final Context context, final String pkg) {
+ AsyncTask.execute(new Runnable() {
+ @Override
+ public void run() {
+ final NotificationManager mgr = context.getSystemService(NotificationManager.class);
+ mgr.removeAutomaticZenRules(pkg);
+ }
+ });
+ }
+
private final class SettingObserver extends ContentObserver {
public SettingObserver() {
super(new Handler(Looper.getMainLooper()));
@@ -160,6 +170,9 @@
}
}
+ /**
+ * Warning dialog when allowing zen access warning about the privileges being granted.
+ */
public static class ScaryWarningDialogFragment extends DialogFragment {
static final String KEY_PKG = "p";
static final String KEY_LABEL = "l";
@@ -202,4 +215,51 @@
.create();
}
}
+
+ /**
+ * Warning dialog when revoking zen access warning that zen rule instances will be deleted.
+ */
+ public static class FriendlyWarningDialogFragment extends DialogFragment {
+ static final String KEY_PKG = "p";
+ static final String KEY_LABEL = "l";
+
+ public FriendlyWarningDialogFragment setPkgInfo(String pkg, CharSequence label) {
+ Bundle args = new Bundle();
+ args.putString(KEY_PKG, pkg);
+ args.putString(KEY_LABEL, TextUtils.isEmpty(label) ? pkg : label.toString());
+ setArguments(args);
+ return this;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final Bundle args = getArguments();
+ final String pkg = args.getString(KEY_PKG);
+ final String label = args.getString(KEY_LABEL);
+
+ final String title = getResources().getString(
+ R.string.zen_access_revoke_warning_dialog_title, label);
+ final String summary = getResources()
+ .getString(R.string.zen_access_revoke_warning_dialog_summary);
+ return new AlertDialog.Builder(getContext())
+ .setMessage(summary)
+ .setTitle(title)
+ .setCancelable(true)
+ .setPositiveButton(R.string.okay,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ deleteRules(getContext(), pkg);
+ setAccess(getContext(), pkg, false);
+ }
+ })
+ .setNegativeButton(R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ // pass
+ }
+ })
+ .create();
+ }
+ }
}
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
index dbbd9a9..c2473ad 100644
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java
@@ -156,7 +156,10 @@
root.removeAll();
final AutomaticZenRule[] sortedRules = sortedRules();
for (AutomaticZenRule sortedRule : sortedRules) {
- root.addPreference(new ZenRulePreference(getPrefContext(), sortedRule));
+ ZenRulePreference pref = new ZenRulePreference(getPrefContext(), sortedRule);
+ if (pref.appExists) {
+ root.addPreference(pref);
+ }
}
final Preference p = new Preference(getPrefContext());
p.setIcon(R.drawable.ic_add);
@@ -264,6 +267,7 @@
private class ZenRulePreference extends Preference {
final String mName;
final String mId;
+ final boolean appExists;
public ZenRulePreference(Context context, final AutomaticZenRule rule) {
super(context);
@@ -283,8 +287,11 @@
setSummary(computeRuleSummary(rule, isSystemRule, info.loadLabel(mPm)));
} catch (PackageManager.NameNotFoundException e) {
setIcon(R.drawable.ic_label);
+ appExists = false;
+ return;
}
+ appExists = true;
setTitle(rule.getName());
setPersistent(false);
diff --git a/src/com/android/settings/notification/ZenModeEventRuleSettings.java b/src/com/android/settings/notification/ZenModeEventRuleSettings.java
index d8e7ad1..c5691d4 100644
--- a/src/com/android/settings/notification/ZenModeEventRuleSettings.java
+++ b/src/com/android/settings/notification/ZenModeEventRuleSettings.java
@@ -26,12 +26,12 @@
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.EventInfo;
+import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.PreferenceScreen;
import com.android.internal.logging.MetricsLogger;
-import com.android.settings.DropDownPreference;
import com.android.settings.R;
import java.util.ArrayList;
diff --git a/src/com/android/settings/notification/ZenModePrioritySettings.java b/src/com/android/settings/notification/ZenModePrioritySettings.java
index e3413a7..f479ba3 100644
--- a/src/com/android/settings/notification/ZenModePrioritySettings.java
+++ b/src/com/android/settings/notification/ZenModePrioritySettings.java
@@ -21,13 +21,13 @@
import android.os.Bundle;
import android.service.notification.ZenModeConfig;
import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.PreferenceScreen;
import android.util.Log;
import com.android.internal.logging.MetricsLogger;
-import com.android.settings.DropDownPreference;
import com.android.settings.R;
import com.android.settings.search.Indexable;
diff --git a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
index e8a9c28..b0f12f8 100644
--- a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
+++ b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
@@ -26,6 +26,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.service.notification.ConditionProviderService;
+import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
@@ -39,7 +40,6 @@
import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
-import com.android.settings.DropDownPreference;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.widget.SwitchBar;
diff --git a/src/com/android/settings/print/PrintJobSettingsFragment.java b/src/com/android/settings/print/PrintJobSettingsFragment.java
index d299aa4..80bf166 100644
--- a/src/com/android/settings/print/PrintJobSettingsFragment.java
+++ b/src/com/android/settings/print/PrintJobSettingsFragment.java
@@ -17,7 +17,6 @@
package com.android.settings.print;
import android.content.Context;
-import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.print.PrintJob;
import android.print.PrintJobId;
@@ -50,8 +49,6 @@
private static final String PRINT_JOB_PREFERENCE = "print_job_preference";
private static final String PRINT_JOB_MESSAGE_PREFERENCE = "print_job_message_preference";
- private Drawable mListDivider;
-
private final PrintJobStateChangeListener mPrintJobStateChangeListener =
new PrintJobStateChangeListener() {
@Override
@@ -229,12 +226,12 @@
} break;
}
- String stateReason = info.getStateReason();
- if (!TextUtils.isEmpty(stateReason)) {
+ CharSequence status = info.getStatus();
+ if (!TextUtils.isEmpty(status)) {
if (getPreferenceScreen().findPreference(PRINT_JOB_MESSAGE_PREFERENCE) == null) {
getPreferenceScreen().addPreference(mMessagePreference);
}
- mMessagePreference.setSummary(stateReason);
+ mMessagePreference.setSummary(status);
} else {
getPreferenceScreen().removePreference(mMessagePreference);
}
diff --git a/src/com/android/settings/search/Index.java b/src/com/android/settings/search/Index.java
index 73386fb..3fd06a2 100644
--- a/src/com/android/settings/search/Index.java
+++ b/src/com/android/settings/search/Index.java
@@ -150,7 +150,9 @@
private static final String EMPTY = "";
private static final String NON_BREAKING_HYPHEN = "\u2011";
+ private static final String LIST_DELIMITERS = "[,]\\s*";
private static final String HYPHEN = "-";
+ private static final String SPACE = " ";
private static final String FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER =
"SEARCH_INDEX_DATA_PROVIDER";
@@ -1002,12 +1004,13 @@
final String normalizedSummaryOn = normalizeString(updatedSummaryOn);
final String normalizedSummaryOff = normalizeString(updatedSummaryOff);
+ final String spaceDelimitedKeywords = normalizeKeywords(keywords);
+
updateOneRow(database, locale,
updatedTitle, normalizedTitle, updatedSummaryOn, normalizedSummaryOn,
- updatedSummaryOff, normalizedSummaryOff, entries,
- className, screenTitle, iconResId,
- rank, keywords, intentAction, intentTargetPackage, intentTargetClass, enabled,
- key, userId);
+ updatedSummaryOff, normalizedSummaryOff, entries, className, screenTitle, iconResId,
+ rank, spaceDelimitedKeywords, intentAction, intentTargetPackage, intentTargetClass,
+ enabled, key, userId);
}
private static String normalizeHyphen(String input) {
@@ -1021,11 +1024,14 @@
return REMOVE_DIACRITICALS_PATTERN.matcher(normalized).replaceAll("").toLowerCase();
}
- private void updateOneRow(SQLiteDatabase database, String locale,
- String updatedTitle, String normalizedTitle,
- String updatedSummaryOn, String normalizedSummaryOn,
- String updatedSummaryOff, String normalizedSummaryOff, String entries,
- String className, String screenTitle, int iconResId, int rank, String keywords,
+ private static String normalizeKeywords(String input) {
+ return (input != null) ? input.replaceAll(LIST_DELIMITERS, SPACE) : EMPTY;
+ }
+
+ private void updateOneRow(SQLiteDatabase database, String locale, String updatedTitle,
+ String normalizedTitle, String updatedSummaryOn, String normalizedSummaryOn,
+ String updatedSummaryOff, String normalizedSummaryOff, String entries, String className,
+ String screenTitle, int iconResId, int rank, String spaceDelimitedKeywords,
String intentAction, String intentTargetPackage, String intentTargetClass,
boolean enabled, String key, int userId) {
@@ -1050,7 +1056,7 @@
values.put(IndexColumns.DATA_SUMMARY_OFF, updatedSummaryOff);
values.put(IndexColumns.DATA_SUMMARY_OFF_NORMALIZED, normalizedSummaryOff);
values.put(IndexColumns.DATA_ENTRIES, entries);
- values.put(IndexColumns.DATA_KEYWORDS, keywords);
+ values.put(IndexColumns.DATA_KEYWORDS, spaceDelimitedKeywords);
values.put(IndexColumns.CLASS_NAME, className);
values.put(IndexColumns.SCREEN_TITLE, screenTitle);
values.put(IndexColumns.INTENT_ACTION, intentAction);
diff --git a/src/com/android/settings/search/Ranking.java b/src/com/android/settings/search/Ranking.java
index 4ac4fb8..3d5ff35 100644
--- a/src/com/android/settings/search/Ranking.java
+++ b/src/com/android/settings/search/Ranking.java
@@ -36,6 +36,7 @@
import com.android.settings.applications.ManageDefaultApps;
import com.android.settings.bluetooth.BluetoothSettings;
import com.android.settings.deviceinfo.StorageSettings;
+import com.android.settings.display.ScreenZoomSettings;
import com.android.settings.fuelgauge.BatterySaverSettings;
import com.android.settings.fuelgauge.PowerUsageSummary;
import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
@@ -122,6 +123,7 @@
// Display
sRankMap.put(DisplaySettings.class.getName(), RANK_DISPLAY);
+ sRankMap.put(ScreenZoomSettings.class.getName(), RANK_WIFI);
// Wallpapers
sRankMap.put(WallpaperTypeSettings.class.getName(), RANK_WALLPAPER);
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 376b2eb..f15ff63 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -38,6 +38,7 @@
import com.android.settings.applications.ManageDefaultApps;
import com.android.settings.bluetooth.BluetoothSettings;
import com.android.settings.deviceinfo.StorageSettings;
+import com.android.settings.display.ScreenZoomSettings;
import com.android.settings.fuelgauge.BatterySaverSettings;
import com.android.settings.fuelgauge.PowerUsageSummary;
import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
@@ -131,6 +132,13 @@
HomeSettings.class.getName(),
R.drawable.ic_settings_home));
+ sResMap.put(ScreenZoomSettings.class.getName(),
+ new SearchIndexableResource(
+ Ranking.getRankForClassName(ScreenZoomSettings.class.getName()),
+ NO_DATA_RES_ID,
+ ScreenZoomSettings.class.getName(),
+ R.drawable.ic_settings_display));
+
sResMap.put(DisplaySettings.class.getName(),
new SearchIndexableResource(
Ranking.getRankForClassName(DisplaySettings.class.getName()),
@@ -155,7 +163,7 @@
sResMap.put(SoundSettings.class.getName(),
new SearchIndexableResource(
Ranking.getRankForClassName(SoundSettings.class.getName()),
- R.xml.sound_settings,
+ NO_DATA_RES_ID,
SoundSettings.class.getName(),
R.drawable.ic_settings_sound));
diff --git a/src/com/android/settings/users/UserDetailsSettings.java b/src/com/android/settings/users/UserDetailsSettings.java
index 0dc87aa..9a81d16 100644
--- a/src/com/android/settings/users/UserDetailsSettings.java
+++ b/src/com/android/settings/users/UserDetailsSettings.java
@@ -145,14 +145,15 @@
List<UserInfo> users = mUserManager.getUsers(true);
for (UserInfo user: users) {
if (user.isGuest()) {
+ UserHandle userHandle = UserHandle.of(user.id);
for (String key : mDefaultGuestRestrictions.keySet()) {
mUserManager.setUserRestriction(
- key, mDefaultGuestRestrictions.getBoolean(key));
+ key, mDefaultGuestRestrictions.getBoolean(key), userHandle);
}
}
}
} else {
- UserHandle userHandle = new UserHandle(mUserInfo.id);
+ UserHandle userHandle = UserHandle.of(mUserInfo.id);
mUserManager.setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, !enabled,
userHandle);
mUserManager.setUserRestriction(UserManager.DISALLOW_SMS, !enabled, userHandle);
diff --git a/src/com/android/settings/vpn2/AppPreference.java b/src/com/android/settings/vpn2/AppPreference.java
index 84897be..af4192e 100644
--- a/src/com/android/settings/vpn2/AppPreference.java
+++ b/src/com/android/settings/vpn2/AppPreference.java
@@ -39,18 +39,13 @@
private int mState = STATE_DISCONNECTED;
private String mPackageName;
private String mName;
- private int mUid;
+ private int mUserId = UserHandle.USER_NULL;
- public AppPreference(Context context, OnClickListener onManage, final String packageName,
- int uid) {
+ public AppPreference(Context context, OnClickListener onManage) {
super(context, null /* attrs */, onManage);
- mPackageName = packageName;
- mUid = uid;
- update();
}
public PackageInfo getPackageInfo() {
- UserHandle user = new UserHandle(UserHandle.getUserId(mUid));
try {
PackageManager pm = getUserContext().getPackageManager();
return pm.getPackageInfo(mPackageName, 0 /* flags */);
@@ -67,8 +62,18 @@
return mPackageName;
}
- public int getUid() {
- return mUid;
+ public void setPackageName(String name) {
+ mPackageName = name;
+ update();
+ }
+
+ public int getUserId() {
+ return mUserId;
+ }
+
+ public void setUserId(int userId) {
+ mUserId = userId;
+ update();
}
public int getState() {
@@ -81,6 +86,10 @@
}
private void update() {
+ if (mPackageName == null || mUserId == UserHandle.USER_NULL) {
+ return;
+ }
+
final String[] states = getContext().getResources().getStringArray(R.array.vpn_states);
setSummary(mState != STATE_DISCONNECTED ? states[mState] : "");
@@ -116,7 +125,7 @@
}
private Context getUserContext() throws PackageManager.NameNotFoundException {
- UserHandle user = new UserHandle(UserHandle.getUserId(mUid));
+ UserHandle user = UserHandle.of(mUserId);
return getContext().createPackageContextAsUser(
getContext().getPackageName(), 0 /* flags */, user);
}
@@ -128,7 +137,7 @@
if ((result = another.mState - mState) == 0 &&
(result = mName.compareToIgnoreCase(another.mName)) == 0 &&
(result = mPackageName.compareTo(another.mPackageName)) == 0) {
- result = mUid - another.mUid;
+ result = mUserId - another.mUserId;
}
return result;
} else if (preference instanceof ConfigPreference) {
diff --git a/src/com/android/settings/vpn2/ConfigPreference.java b/src/com/android/settings/vpn2/ConfigPreference.java
index a2736a0..c7ecddb 100644
--- a/src/com/android/settings/vpn2/ConfigPreference.java
+++ b/src/com/android/settings/vpn2/ConfigPreference.java
@@ -31,12 +31,15 @@
* state.
*/
public class ConfigPreference extends ManageablePreference {
- private VpnProfile mProfile;
- private int mState = -1;
+ public static int STATE_NONE = -1;
- ConfigPreference(Context context, OnClickListener onManage, VpnProfile profile) {
+ private VpnProfile mProfile;
+
+ /** One of the STATE_* fields from LegacyVpnInfo, or STATE_NONE */
+ private int mState = STATE_NONE;
+
+ ConfigPreference(Context context, OnClickListener onManage) {
super(context, null /* attrs */, onManage);
- setProfile(profile);
}
public VpnProfile getProfile() {
@@ -54,15 +57,16 @@
}
private void update() {
- if (mState < 0) {
+ if (mState == STATE_NONE) {
setSummary("");
} else {
- String[] states = getContext().getResources()
- .getStringArray(R.array.vpn_states);
+ final String[] states = getContext().getResources().getStringArray(R.array.vpn_states);
setSummary(states[mState]);
}
- setIcon(R.mipmap.ic_launcher_settings);
- setTitle(mProfile.name);
+ if (mProfile != null) {
+ setIcon(R.mipmap.ic_launcher_settings);
+ setTitle(mProfile.name);
+ }
notifyHierarchyChanged();
}
@@ -72,7 +76,7 @@
ConfigPreference another = (ConfigPreference) preference;
int result;
if ((result = another.mState - mState) == 0 &&
- (result = mProfile.name.compareTo(another.mProfile.name)) == 0 &&
+ (result = mProfile.name.compareToIgnoreCase(another.mProfile.name)) == 0 &&
(result = mProfile.type - another.mProfile.type) == 0) {
result = mProfile.key.compareTo(another.mProfile.key);
}
diff --git a/src/com/android/settings/vpn2/VpnSettings.java b/src/com/android/settings/vpn2/VpnSettings.java
index b903463..00f6a12 100644
--- a/src/com/android/settings/vpn2/VpnSettings.java
+++ b/src/com/android/settings/vpn2/VpnSettings.java
@@ -16,13 +16,16 @@
package com.android.settings.vpn2;
+import android.annotation.NonNull;
+import android.annotation.UiThread;
+import android.annotation.WorkerThread;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
+import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -40,7 +43,9 @@
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
-import android.util.SparseArray;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -57,8 +62,10 @@
import com.google.android.collect.Lists;
import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import static android.app.AppOpsManager.OP_ACTIVATE_VPN;
@@ -87,8 +94,8 @@
private final KeyStore mKeyStore = KeyStore.getInstance();
- private HashMap<String, ConfigPreference> mConfigPreferences = new HashMap<>();
- private HashMap<String, AppPreference> mAppPreferences = new HashMap<>();
+ private Map<String, ConfigPreference> mConfigPreferences = new ArrayMap<>();
+ private Map<AppVpnInfo, AppPreference> mAppPreferences = new ArrayMap<>();
private Handler mUpdater;
private LegacyVpnInfo mConnectedLegacyVpn;
@@ -211,58 +218,64 @@
public boolean handleMessage(Message message) {
mUpdater.removeMessages(RESCAN_MESSAGE);
- // Pref group within which to list VPNs
- PreferenceGroup vpnGroup = getPreferenceScreen();
- vpnGroup.removeAll();
- mConfigPreferences.clear();
- mAppPreferences.clear();
+ final List<VpnProfile> vpnProfiles = loadVpnProfiles(mKeyStore);
+ final List<AppVpnInfo> vpnApps = getVpnApps();
- // Fetch configured VPN profiles from KeyStore
- for (VpnProfile profile : loadVpnProfiles(mKeyStore)) {
- final ConfigPreference pref = new ConfigPreference(getPrefContext(), mManageListener,
- profile);
- pref.setOnPreferenceClickListener(this);
- mConfigPreferences.put(profile.key, pref);
- vpnGroup.addPreference(pref);
- }
+ final List<LegacyVpnInfo> connectedLegacyVpns = getConnectedLegacyVpns();
+ final List<AppVpnInfo> connectedAppVpns = getConnectedAppVpns();
- // 3rd-party VPN apps can change elsewhere. Reload them every time.
- for (AppOpsManager.PackageOps pkg : getVpnApps()) {
- String key = getVpnIdentifier(UserHandle.getUserId(pkg.getUid()), pkg.getPackageName());
- final AppPreference pref = new AppPreference(getPrefContext(), mManageListener,
- pkg.getPackageName(), pkg.getUid());
- pref.setOnPreferenceClickListener(this);
- mAppPreferences.put(key, pref);
- vpnGroup.addPreference(pref);
- }
+ // Refresh the PreferenceGroup which lists VPNs
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ // Find new VPNs by subtracting existing ones from the full set
+ final Set<Preference> updates = new ArraySet<>();
- // Mark out connections with a subtitle
- try {
- // Legacy VPNs
- mConnectedLegacyVpn = null;
- LegacyVpnInfo info = mConnectivityService.getLegacyVpnInfo(UserHandle.myUserId());
- if (info != null) {
- ConfigPreference preference = mConfigPreferences.get(info.key);
- if (preference != null) {
- preference.setState(info.state);
- mConnectedLegacyVpn = info;
+ for (VpnProfile profile : vpnProfiles) {
+ ConfigPreference p = findOrCreatePreference(profile);
+ p.setState(ConfigPreference.STATE_NONE);
+ updates.add(p);
}
- }
+ for (AppVpnInfo app : vpnApps) {
+ AppPreference p = findOrCreatePreference(app);
+ p.setState(AppPreference.STATE_DISCONNECTED);
+ updates.add(p);
+ }
- // Third-party VPNs
- for (UserHandle profile : mUserManager.getUserProfiles()) {
- VpnConfig cfg = mConnectivityService.getVpnConfig(profile.getIdentifier());
- if (cfg != null) {
- final String key = getVpnIdentifier(profile.getIdentifier(), cfg.user);
- final AppPreference preference = mAppPreferences.get(key);
+ // Trim preferences for deleted VPNs
+ mConfigPreferences.values().retainAll(updates);
+ mAppPreferences.values().retainAll(updates);
+
+ final PreferenceGroup vpnGroup = getPreferenceScreen();
+ for (int i = vpnGroup.getPreferenceCount() - 1; i >= 0; i--) {
+ Preference p = vpnGroup.getPreference(i);
+ if (updates.contains(p)) {
+ updates.remove(p);
+ } else {
+ vpnGroup.removePreference(p);
+ }
+ }
+
+ // Show any new preferences on the screen
+ for (Preference pref : updates) {
+ vpnGroup.addPreference(pref);
+ }
+
+ // Mark connected VPNs
+ for (LegacyVpnInfo info : connectedLegacyVpns) {
+ final ConfigPreference preference = mConfigPreferences.get(info.key);
+ if (preference != null) {
+ preference.setState(info.state);
+ }
+ }
+ for (AppVpnInfo app : connectedAppVpns) {
+ final AppPreference preference = mAppPreferences.get(app);
if (preference != null) {
preference.setState(AppPreference.STATE_CONNECTED);
}
}
}
- } catch (RemoteException e) {
- // ignore
- }
+ });
mUpdater.sendEmptyMessageDelayed(RESCAN_MESSAGE, RESCAN_INTERVAL_MS);
return true;
@@ -278,7 +291,7 @@
mConnectedLegacyVpn.intent.send();
return true;
} catch (Exception e) {
- // ignore
+ Log.w(LOG_TAG, "Starting config intent failed", e);
}
}
ConfigDialogFragment.show(this, profile, false /* editing */, true /* exists */);
@@ -289,7 +302,7 @@
if (!connected) {
try {
- UserHandle user = new UserHandle(UserHandle.getUserId(pref.getUid()));
+ UserHandle user = UserHandle.of(pref.getUserId());
Context userContext = getActivity().createPackageContextAsUser(
getActivity().getPackageName(), 0 /* flags */, user);
PackageManager pm = userContext.getPackageManager();
@@ -299,11 +312,11 @@
return true;
}
} catch (PackageManager.NameNotFoundException nnfe) {
- // Fall through
+ Log.w(LOG_TAG, "VPN provider does not exist: " + pref.getPackageName(), nnfe);
}
}
- // Already onnected or no launch intent available - show an info dialog
+ // Already connected or no launch intent available - show an info dialog
PackageInfo pkgInfo = pref.getPackageInfo();
AppDialogFragment.show(this, pkgInfo, pref.getLabel(), false /* editing */, connected);
return true;
@@ -311,6 +324,11 @@
return false;
}
+ @Override
+ protected int getHelpResource() {
+ return R.string.help_url_vpn;
+ }
+
private View.OnClickListener mManageListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
@@ -329,10 +347,6 @@
}
};
- private static String getVpnIdentifier(int userId, String packageName) {
- return Integer.toString(userId)+ "_" + packageName;
- }
-
private NetworkCallback mNetworkCallback = new NetworkCallback() {
@Override
public void onAvailable(Network network) {
@@ -349,18 +363,68 @@
}
};
- @Override
- protected int getHelpResource() {
- return R.string.help_url_vpn;
+ @UiThread
+ private ConfigPreference findOrCreatePreference(VpnProfile profile) {
+ ConfigPreference pref = mConfigPreferences.get(profile.key);
+ if (pref == null) {
+ pref = new ConfigPreference(getPrefContext(), mManageListener);
+ pref.setOnPreferenceClickListener(this);
+ mConfigPreferences.put(profile.key, pref);
+ }
+ pref.setProfile(profile);
+ return pref;
}
- private List<AppOpsManager.PackageOps> getVpnApps() {
- List<AppOpsManager.PackageOps> result = Lists.newArrayList();
+ @UiThread
+ private AppPreference findOrCreatePreference(AppVpnInfo app) {
+ AppPreference pref = mAppPreferences.get(app);
+ if (pref == null) {
+ pref = new AppPreference(getPrefContext(), mManageListener);
+ pref.setOnPreferenceClickListener(this);
+ mAppPreferences.put(app, pref);
+ }
+ pref.setUserId(app.userId);
+ pref.setPackageName(app.packageName);
+ return pref;
+ }
+
+ @WorkerThread
+ private List<LegacyVpnInfo> getConnectedLegacyVpns() {
+ try {
+ mConnectedLegacyVpn = mConnectivityService.getLegacyVpnInfo(UserHandle.myUserId());
+ if (mConnectedLegacyVpn != null) {
+ return Collections.singletonList(mConnectedLegacyVpn);
+ }
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Failure updating VPN list with connected legacy VPNs", e);
+ }
+ return Collections.emptyList();
+ }
+
+ @WorkerThread
+ private List<AppVpnInfo> getConnectedAppVpns() {
+ // Mark connected third-party services
+ List<AppVpnInfo> connections = new ArrayList<>();
+ try {
+ for (UserHandle profile : mUserManager.getUserProfiles()) {
+ VpnConfig config = mConnectivityService.getVpnConfig(profile.getIdentifier());
+ if (config != null && !config.legacy) {
+ connections.add(new AppVpnInfo(profile.getIdentifier(), config.user));
+ }
+ }
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "Failure updating VPN list with connected app VPNs", e);
+ }
+ return connections;
+ }
+
+ private List<AppVpnInfo> getVpnApps() {
+ List<AppVpnInfo> result = Lists.newArrayList();
// Build a filter of currently active user profiles.
- SparseArray<Boolean> currentProfileIds = new SparseArray<>();
+ Set<Integer> currentProfileIds = new ArraySet<>();
for (UserHandle profile : mUserManager.getUserProfiles()) {
- currentProfileIds.put(profile.getIdentifier(), Boolean.TRUE);
+ currentProfileIds.add(profile.getIdentifier());
}
// Fetch VPN-enabled apps from AppOps.
@@ -369,7 +433,7 @@
if (apps != null) {
for (AppOpsManager.PackageOps pkg : apps) {
int userId = UserHandle.getUserId(pkg.getUid());
- if (currentProfileIds.get(userId) == null) {
+ if (!currentProfileIds.contains(userId)) {
// Skip packages for users outside of our profile group.
continue;
}
@@ -382,7 +446,7 @@
}
}
if (allowed) {
- result.add(pkg);
+ result.add(new AppVpnInfo(userId, pkg.getPackageName()));
}
}
}
@@ -407,4 +471,29 @@
}
return result;
}
+
+ /** Utility holder for packageName:userId pairs */
+ private static class AppVpnInfo {
+ public int userId;
+ public String packageName;
+
+ public AppVpnInfo(int userId, @NonNull String packageName) {
+ this.userId = userId;
+ this.packageName = packageName;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof AppVpnInfo) {
+ AppVpnInfo that = (AppVpnInfo) other;
+ return userId == that.userId && packageName.equals(that.packageName);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return (packageName != null ? packageName.hashCode() : 0) * 31 + userId;
+ }
+ }
}
diff --git a/src/com/android/settings/wifi/AdvancedWifiSettings.java b/src/com/android/settings/wifi/AdvancedWifiSettings.java
index aaab0c5..8dfb024 100644
--- a/src/com/android/settings/wifi/AdvancedWifiSettings.java
+++ b/src/com/android/settings/wifi/AdvancedWifiSettings.java
@@ -18,68 +18,25 @@
import android.app.Dialog;
import android.app.DialogFragment;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.NetworkScoreManager;
-import android.net.NetworkScorerAppManager;
-import android.net.NetworkScorerAppManager.NetworkScorerAppData;
-import android.net.wifi.WifiInfo;
-import android.net.wifi.WifiManager;
import android.net.wifi.WpsInfo;
import android.os.Bundle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.provider.Settings.Global;
import android.security.Credentials;
-import android.support.v14.preference.SwitchPreference;
-import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
-import android.text.TextUtils;
-import android.util.Log;
-import android.widget.Toast;
-
import com.android.internal.logging.MetricsLogger;
-import com.android.settings.AppListSwitchPreference;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.Utils;
-import java.util.Collection;
-
-public class AdvancedWifiSettings extends SettingsPreferenceFragment
- implements Preference.OnPreferenceChangeListener {
-
+public class AdvancedWifiSettings extends SettingsPreferenceFragment {
private static final String TAG = "AdvancedWifiSettings";
- private static final String KEY_MAC_ADDRESS = "mac_address";
- private static final String KEY_CURRENT_IP_ADDRESS = "current_ip_address";
- private static final String KEY_FREQUENCY_BAND = "frequency_band";
- private static final String KEY_NOTIFY_OPEN_NETWORKS = "notify_open_networks";
- private static final String KEY_SLEEP_POLICY = "sleep_policy";
+
private static final String KEY_INSTALL_CREDENTIALS = "install_credentials";
- private static final String KEY_WIFI_ASSISTANT = "wifi_assistant";
private static final String KEY_WIFI_DIRECT = "wifi_direct";
private static final String KEY_WPS_PUSH = "wps_push_button";
private static final String KEY_WPS_PIN = "wps_pin_entry";
- private WifiManager mWifiManager;
- private NetworkScoreManager mNetworkScoreManager;
- private AppListSwitchPreference mWifiAssistantPreference;
-
- private IntentFilter mFilter;
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION) ||
- action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
- refreshWifiInfo();
- }
- }
- };
-
@Override
protected int getMetricsCategory() {
return MetricsLogger.WIFI_ADVANCED;
@@ -92,37 +49,13 @@
}
@Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
- mFilter = new IntentFilter();
- mFilter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
- mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- mNetworkScoreManager =
- (NetworkScoreManager) getSystemService(Context.NETWORK_SCORE_SERVICE);
- }
-
- @Override
public void onResume() {
super.onResume();
initPreferences();
- getActivity().registerReceiver(mReceiver, mFilter);
- refreshWifiInfo();
- }
-
- @Override
- public void onPause() {
- super.onPause();
- getActivity().unregisterReceiver(mReceiver);
}
private void initPreferences() {
- SwitchPreference notifyOpenNetworks =
- (SwitchPreference) findPreference(KEY_NOTIFY_OPEN_NETWORKS);
- notifyOpenNetworks.setChecked(Settings.Global.getInt(getContentResolver(),
- Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1);
- notifyOpenNetworks.setEnabled(mWifiManager.isWifiEnabled());
-
+ final Context context = getActivity();
Intent intent = new Intent(Credentials.INSTALL_AS_USER_ACTION);
intent.setClassName("com.android.certinstaller",
"com.android.certinstaller.CertInstallerMain");
@@ -130,16 +63,6 @@
Preference pref = findPreference(KEY_INSTALL_CREDENTIALS);
pref.setIntent(intent);
- final Context context = getActivity();
- mWifiAssistantPreference = (AppListSwitchPreference) findPreference(KEY_WIFI_ASSISTANT);
- Collection<NetworkScorerAppData> scorers =
- NetworkScorerAppManager.getAllValidScorers(context);
- if (UserManager.get(context).isAdminUser() && !scorers.isEmpty()) {
- mWifiAssistantPreference.setOnPreferenceChangeListener(this);
- initWifiAssistantPreference(scorers);
- } else if (mWifiAssistantPreference != null) {
- getPreferenceScreen().removePreference(mWifiAssistantPreference);
- }
Intent wifiDirectIntent = new Intent(context,
com.android.settings.Settings.WifiP2pSettingsActivity.class);
@@ -165,165 +88,6 @@
return true;
}
});
-
- ListPreference frequencyPref = (ListPreference) findPreference(KEY_FREQUENCY_BAND);
-
- if (mWifiManager.isDualBandSupported()) {
- frequencyPref.setOnPreferenceChangeListener(this);
- int value = mWifiManager.getFrequencyBand();
- if (value != -1) {
- frequencyPref.setValue(String.valueOf(value));
- updateFrequencyBandSummary(frequencyPref, value);
- } else {
- Log.e(TAG, "Failed to fetch frequency band");
- }
- } else {
- if (frequencyPref != null) {
- // null if it has already been removed before resume
- getPreferenceScreen().removePreference(frequencyPref);
- }
- }
-
- ListPreference sleepPolicyPref = (ListPreference) findPreference(KEY_SLEEP_POLICY);
- if (sleepPolicyPref != null) {
- if (Utils.isWifiOnly(context)) {
- sleepPolicyPref.setEntries(R.array.wifi_sleep_policy_entries_wifi_only);
- }
- sleepPolicyPref.setOnPreferenceChangeListener(this);
- int value = Settings.Global.getInt(getContentResolver(),
- Settings.Global.WIFI_SLEEP_POLICY,
- Settings.Global.WIFI_SLEEP_POLICY_NEVER);
- String stringValue = String.valueOf(value);
- sleepPolicyPref.setValue(stringValue);
- updateSleepPolicySummary(sleepPolicyPref, stringValue);
- }
- }
-
- private void initWifiAssistantPreference(Collection<NetworkScorerAppData> scorers) {
- int count = scorers.size();
- String[] packageNames = new String[count];
- int i = 0;
- for (NetworkScorerAppData scorer : scorers) {
- packageNames[i] = scorer.mPackageName;
- i++;
- }
- mWifiAssistantPreference.setPackageNames(packageNames,
- mNetworkScoreManager.getActiveScorerPackage());
- }
-
- private void updateSleepPolicySummary(Preference sleepPolicyPref, String value) {
- if (value != null) {
- String[] values = getResources().getStringArray(R.array.wifi_sleep_policy_values);
- final int summaryArrayResId = Utils.isWifiOnly(getActivity()) ?
- R.array.wifi_sleep_policy_entries_wifi_only : R.array.wifi_sleep_policy_entries;
- String[] summaries = getResources().getStringArray(summaryArrayResId);
- for (int i = 0; i < values.length; i++) {
- if (value.equals(values[i])) {
- if (i < summaries.length) {
- sleepPolicyPref.setSummary(summaries[i]);
- return;
- }
- }
- }
- }
-
- sleepPolicyPref.setSummary("");
- Log.e(TAG, "Invalid sleep policy value: " + value);
- }
-
- private void updateFrequencyBandSummary(Preference frequencyBandPref, int index) {
- String[] summaries = getResources().getStringArray(R.array.wifi_frequency_band_entries);
- frequencyBandPref.setSummary(summaries[index]);
- }
-
- @Override
- public boolean onPreferenceTreeClick(Preference preference) {
- String key = preference.getKey();
-
- if (KEY_NOTIFY_OPEN_NETWORKS.equals(key)) {
- Global.putInt(getContentResolver(),
- Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
- ((SwitchPreference) preference).isChecked() ? 1 : 0);
- } else {
- return super.onPreferenceTreeClick(preference);
- }
- return true;
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- final Context context = getActivity();
- String key = preference.getKey();
-
- if (KEY_FREQUENCY_BAND.equals(key)) {
- try {
- int value = Integer.parseInt((String) newValue);
- mWifiManager.setFrequencyBand(value, true);
- updateFrequencyBandSummary(preference, value);
- } catch (NumberFormatException e) {
- Toast.makeText(context, R.string.wifi_setting_frequency_band_error,
- Toast.LENGTH_SHORT).show();
- return false;
- }
- } else if (KEY_WIFI_ASSISTANT.equals(key)) {
- NetworkScorerAppData wifiAssistant =
- NetworkScorerAppManager.getScorer(context, (String) newValue);
- if (wifiAssistant == null) {
- mNetworkScoreManager.setActiveScorer(null);
- return true;
- }
-
- Intent intent = new Intent();
- if (wifiAssistant.mConfigurationActivityClassName != null) {
- // App has a custom configuration activity; launch that.
- // This custom activity will be responsible for launching the system
- // dialog.
- intent.setClassName(wifiAssistant.mPackageName,
- wifiAssistant.mConfigurationActivityClassName);
- } else {
- // Fall back on the system dialog.
- intent.setAction(NetworkScoreManager.ACTION_CHANGE_ACTIVE);
- intent.putExtra(NetworkScoreManager.EXTRA_PACKAGE_NAME,
- wifiAssistant.mPackageName);
- }
-
- startActivity(intent);
- // Don't update the preference widget state until the child activity returns.
- // It will be updated in onResume after the activity finishes.
- return false;
- }
-
- if (KEY_SLEEP_POLICY.equals(key)) {
- try {
- String stringValue = (String) newValue;
- Settings.Global.putInt(getContentResolver(), Settings.Global.WIFI_SLEEP_POLICY,
- Integer.parseInt(stringValue));
- updateSleepPolicySummary(preference, stringValue);
- } catch (NumberFormatException e) {
- Toast.makeText(context, R.string.wifi_setting_sleep_policy_error,
- Toast.LENGTH_SHORT).show();
- return false;
- }
- }
-
- return true;
- }
-
- private void refreshWifiInfo() {
- final Context context = getActivity();
- WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
-
- Preference wifiMacAddressPref = findPreference(KEY_MAC_ADDRESS);
- String macAddress = wifiInfo == null ? null : wifiInfo.getMacAddress();
- wifiMacAddressPref.setSummary(!TextUtils.isEmpty(macAddress) ? macAddress
- : context.getString(R.string.status_unavailable));
- wifiMacAddressPref.setSelectable(false);
-
- Preference wifiIpAddressPref = findPreference(KEY_CURRENT_IP_ADDRESS);
- String ipAddress = Utils.getWifiIpAddresses(context);
- wifiIpAddressPref.setSummary(ipAddress == null ?
- context.getString(R.string.status_unavailable) : ipAddress);
- wifiIpAddressPref.setSelectable(false);
}
/* Wrapper class for the WPS dialog to properly handle life cycle events like rotation. */
diff --git a/src/com/android/settings/wifi/ConfigureWifiSettings.java b/src/com/android/settings/wifi/ConfigureWifiSettings.java
new file mode 100644
index 0000000..54ce036
--- /dev/null
+++ b/src/com/android/settings/wifi/ConfigureWifiSettings.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2015 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.wifi;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.NetworkScoreManager;
+import android.net.NetworkScorerAppManager;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Bundle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.Preference;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.Toast;
+import com.android.settings.AppListSwitchPreference;
+import com.android.settings.InstrumentedFragment;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.Utils;
+
+import java.util.Collection;
+import java.util.List;
+
+public class ConfigureWifiSettings extends SettingsPreferenceFragment
+ implements Preference.OnPreferenceChangeListener {
+ private static final String TAG = "ConfigureWifiSettings";
+
+ private static final String KEY_MAC_ADDRESS = "mac_address";
+ private static final String KEY_SAVED_NETWORKS = "saved_networks";
+ private static final String KEY_CURRENT_IP_ADDRESS = "current_ip_address";
+ private static final String KEY_FREQUENCY_BAND = "frequency_band";
+ private static final String KEY_NOTIFY_OPEN_NETWORKS = "notify_open_networks";
+ private static final String KEY_SLEEP_POLICY = "sleep_policy";
+ private static final String KEY_WIFI_ASSISTANT = "wifi_assistant";
+
+ private WifiManager mWifiManager;
+ private NetworkScoreManager mNetworkScoreManager;
+ private AppListSwitchPreference mWifiAssistantPreference;
+
+ private IntentFilter mFilter;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ addPreferencesFromResource(R.xml.wifi_configure_settings);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+ mFilter = new IntentFilter();
+ mFilter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
+ mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ mNetworkScoreManager =
+ (NetworkScoreManager) getSystemService(Context.NETWORK_SCORE_SERVICE);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ initPreferences();
+ getActivity().registerReceiver(mReceiver, mFilter);
+ refreshWifiInfo();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ getActivity().unregisterReceiver(mReceiver);
+ }
+
+ private void initPreferences() {
+ List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
+ if (configs == null || configs.size() == 0) {
+ removePreference(KEY_SAVED_NETWORKS);
+ }
+
+ SwitchPreference notifyOpenNetworks =
+ (SwitchPreference) findPreference(KEY_NOTIFY_OPEN_NETWORKS);
+ notifyOpenNetworks.setChecked(Settings.Global.getInt(getContentResolver(),
+ Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1);
+ notifyOpenNetworks.setEnabled(mWifiManager.isWifiEnabled());
+
+ final Context context = getActivity();
+ mWifiAssistantPreference = (AppListSwitchPreference) findPreference(KEY_WIFI_ASSISTANT);
+ Collection<NetworkScorerAppManager.NetworkScorerAppData> scorers =
+ NetworkScorerAppManager.getAllValidScorers(context);
+ if (UserManager.get(context).isAdminUser() && !scorers.isEmpty()) {
+ mWifiAssistantPreference.setOnPreferenceChangeListener(this);
+ initWifiAssistantPreference(scorers);
+ } else if (mWifiAssistantPreference != null) {
+ getPreferenceScreen().removePreference(mWifiAssistantPreference);
+ }
+
+ ListPreference frequencyPref = (ListPreference) findPreference(KEY_FREQUENCY_BAND);
+
+ if (mWifiManager.isDualBandSupported()) {
+ frequencyPref.setOnPreferenceChangeListener(this);
+ int value = mWifiManager.getFrequencyBand();
+ if (value != -1) {
+ frequencyPref.setValue(String.valueOf(value));
+ updateFrequencyBandSummary(frequencyPref, value);
+ } else {
+ Log.e(TAG, "Failed to fetch frequency band");
+ }
+ } else {
+ if (frequencyPref != null) {
+ // null if it has already been removed before resume
+ getPreferenceScreen().removePreference(frequencyPref);
+ }
+ }
+
+ ListPreference sleepPolicyPref = (ListPreference) findPreference(KEY_SLEEP_POLICY);
+ if (sleepPolicyPref != null) {
+ if (Utils.isWifiOnly(context)) {
+ sleepPolicyPref.setEntries(R.array.wifi_sleep_policy_entries_wifi_only);
+ }
+ sleepPolicyPref.setOnPreferenceChangeListener(this);
+ int value = Settings.Global.getInt(getContentResolver(),
+ Settings.Global.WIFI_SLEEP_POLICY,
+ Settings.Global.WIFI_SLEEP_POLICY_NEVER);
+ String stringValue = String.valueOf(value);
+ sleepPolicyPref.setValue(stringValue);
+ updateSleepPolicySummary(sleepPolicyPref, stringValue);
+ }
+ }
+
+ private void updateSleepPolicySummary(Preference sleepPolicyPref, String value) {
+ if (value != null) {
+ String[] values = getResources().getStringArray(R.array.wifi_sleep_policy_values);
+ final int summaryArrayResId = Utils.isWifiOnly(getActivity()) ?
+ R.array.wifi_sleep_policy_entries_wifi_only : R.array.wifi_sleep_policy_entries;
+ String[] summaries = getResources().getStringArray(summaryArrayResId);
+ for (int i = 0; i < values.length; i++) {
+ if (value.equals(values[i])) {
+ if (i < summaries.length) {
+ sleepPolicyPref.setSummary(summaries[i]);
+ return;
+ }
+ }
+ }
+ }
+
+ sleepPolicyPref.setSummary("");
+ Log.e(TAG, "Invalid sleep policy value: " + value);
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(Preference preference) {
+ String key = preference.getKey();
+
+ if (KEY_NOTIFY_OPEN_NETWORKS.equals(key)) {
+ Settings.Global.putInt(getContentResolver(),
+ Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
+ ((SwitchPreference) preference).isChecked() ? 1 : 0);
+ } else {
+ return super.onPreferenceTreeClick(preference);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final Context context = getActivity();
+ String key = preference.getKey();
+
+ if (KEY_FREQUENCY_BAND.equals(key)) {
+ try {
+ int value = Integer.parseInt((String) newValue);
+ mWifiManager.setFrequencyBand(value, true);
+ updateFrequencyBandSummary(preference, value);
+ } catch (NumberFormatException e) {
+ Toast.makeText(context, R.string.wifi_setting_frequency_band_error,
+ Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ } else if (KEY_WIFI_ASSISTANT.equals(key)) {
+ NetworkScorerAppManager.NetworkScorerAppData wifiAssistant =
+ NetworkScorerAppManager.getScorer(context, (String) newValue);
+ if (wifiAssistant == null) {
+ mNetworkScoreManager.setActiveScorer(null);
+ return true;
+ }
+
+ Intent intent = new Intent();
+ if (wifiAssistant.mConfigurationActivityClassName != null) {
+ // App has a custom configuration activity; launch that.
+ // This custom activity will be responsible for launching the system
+ // dialog.
+ intent.setClassName(wifiAssistant.mPackageName,
+ wifiAssistant.mConfigurationActivityClassName);
+ } else {
+ // Fall back on the system dialog.
+ intent.setAction(NetworkScoreManager.ACTION_CHANGE_ACTIVE);
+ intent.putExtra(NetworkScoreManager.EXTRA_PACKAGE_NAME,
+ wifiAssistant.mPackageName);
+ }
+
+ startActivity(intent);
+ // Don't update the preference widget state until the child activity returns.
+ // It will be updated in onResume after the activity finishes.
+ return false;
+ }
+
+ if (KEY_SLEEP_POLICY.equals(key)) {
+ try {
+ String stringValue = (String) newValue;
+ Settings.Global.putInt(getContentResolver(), Settings.Global.WIFI_SLEEP_POLICY,
+ Integer.parseInt(stringValue));
+ updateSleepPolicySummary(preference, stringValue);
+ } catch (NumberFormatException e) {
+ Toast.makeText(context, R.string.wifi_setting_sleep_policy_error,
+ Toast.LENGTH_SHORT).show();
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private void refreshWifiInfo() {
+ final Context context = getActivity();
+ WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+
+ Preference wifiMacAddressPref = findPreference(KEY_MAC_ADDRESS);
+ String macAddress = wifiInfo == null ? null : wifiInfo.getMacAddress();
+ wifiMacAddressPref.setSummary(!TextUtils.isEmpty(macAddress) ? macAddress
+ : context.getString(R.string.status_unavailable));
+ wifiMacAddressPref.setSelectable(false);
+
+ Preference wifiIpAddressPref = findPreference(KEY_CURRENT_IP_ADDRESS);
+ String ipAddress = Utils.getWifiIpAddresses(context);
+ wifiIpAddressPref.setSummary(ipAddress == null ?
+ context.getString(R.string.status_unavailable) : ipAddress);
+ wifiIpAddressPref.setSelectable(false);
+ }
+
+ private void updateFrequencyBandSummary(Preference frequencyBandPref, int index) {
+ String[] summaries = getResources().getStringArray(R.array.wifi_frequency_band_entries);
+ frequencyBandPref.setSummary(summaries[index]);
+ }
+
+ private void initWifiAssistantPreference(
+ Collection<NetworkScorerAppManager.NetworkScorerAppData> scorers) {
+ int count = scorers.size();
+ String[] packageNames = new String[count];
+ int i = 0;
+ for (NetworkScorerAppManager.NetworkScorerAppData scorer : scorers) {
+ packageNames[i] = scorer.mPackageName;
+ i++;
+ }
+ mWifiAssistantPreference.setPackageNames(packageNames,
+ mNetworkScoreManager.getActiveScorerPackage());
+ }
+
+ @Override
+ protected int getMetricsCategory() {
+ return InstrumentedFragment.CONFIGURE_WIFI;
+ }
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION) ||
+ action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+ refreshWifiInfo();
+ }
+ }
+ };
+}
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 74d3e51..87f72f5 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -32,7 +32,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
-import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
@@ -47,9 +47,11 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceViewHolder;
import android.text.Spannable;
import android.text.style.TextAppearanceSpan;
import android.util.Log;
+import android.util.TypedValue;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
@@ -99,14 +101,13 @@
/* package */ static final int MENU_ID_WPS_PBC = Menu.FIRST;
private static final int MENU_ID_WPS_PIN = Menu.FIRST + 1;
- private static final int MENU_ID_SAVED_NETWORK = Menu.FIRST + 2;
- /* package */ static final int MENU_ID_ADD_NETWORK = Menu.FIRST + 3;
private static final int MENU_ID_ADVANCED = Menu.FIRST + 4;
private static final int MENU_ID_SCAN = Menu.FIRST + 5;
private static final int MENU_ID_CONNECT = Menu.FIRST + 6;
private static final int MENU_ID_FORGET = Menu.FIRST + 7;
private static final int MENU_ID_MODIFY = Menu.FIRST + 8;
private static final int MENU_ID_WRITE_NFC = Menu.FIRST + 9;
+ private static final int MENU_ID_CONFIGURE = Menu.FIRST + 10;
public static final int WIFI_DIALOG_ID = 1;
/* package */ static final int WPS_PBC_DIALOG_ID = 2;
@@ -118,8 +119,6 @@
private static final String SAVE_DIALOG_ACCESS_POINT_STATE = "wifi_ap_state";
private static final String SAVED_WIFI_NFC_DIALOG_STATE = "wifi_nfc_dlg_state";
- private static boolean savedNetworksExist;
-
protected WifiManager mWifiManager;
private WifiManager.ActionListener mConnectListener;
private WifiManager.ActionListener mSaveListener;
@@ -157,6 +156,7 @@
private HandlerThread mBgThread;
private UserBadgeCache mUserBadgeCache;
+ private Preference mAddPreference;
/* End of "used in Wifi Setup context" */
@@ -177,6 +177,14 @@
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.wifi_settings);
+ mAddPreference = new Preference(getContext());
+ Drawable ic_add = getContext().getDrawable(R.drawable.ic_menu_add).mutate();
+ TypedValue tv = new TypedValue();
+ getContext().getTheme().resolveAttribute(android.R.attr.colorAccent, tv, true);
+ ic_add.setTint(getContext().getColor(tv.resourceId));
+ mAddPreference.setIcon(ic_add);
+ mAddPreference.setTitle(R.string.wifi_add_network);
+
mUserBadgeCache = new UserBadgeCache(getPackageManager());
mBgThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
@@ -343,24 +351,14 @@
*/
void addOptionsMenuItems(Menu menu) {
final boolean wifiIsEnabled = mWifiTracker.isWifiEnabled();
- TypedArray ta = getActivity().getTheme().obtainStyledAttributes(
- new int[] {R.attr.ic_menu_add, R.attr.ic_wps});
- menu.add(Menu.NONE, MENU_ID_ADD_NETWORK, 0, R.string.wifi_add_network)
- .setIcon(ta.getDrawable(0))
- .setEnabled(wifiIsEnabled)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- if (savedNetworksExist) {
- menu.add(Menu.NONE, MENU_ID_SAVED_NETWORK, 0, R.string.wifi_saved_access_points_label)
- .setIcon(ta.getDrawable(0))
- .setEnabled(wifiIsEnabled)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- }
menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.menu_stats_refresh)
.setEnabled(wifiIsEnabled)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- ta.recycle();
+ menu.add(Menu.NONE, MENU_ID_CONFIGURE, 0, R.string.wifi_menu_configure)
+ .setIcon(R.drawable.ic_settings_24dp)
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
@Override
@@ -419,22 +417,6 @@
MetricsLogger.action(getActivity(), MetricsLogger.ACTION_WIFI_FORCE_SCAN);
mWifiTracker.forceScan();
return true;
- case MENU_ID_ADD_NETWORK:
- if (mWifiTracker.isWifiEnabled()) {
- onAddNetworkPressed();
- }
- return true;
- case MENU_ID_SAVED_NETWORK:
- if (getActivity() instanceof SettingsActivity) {
- ((SettingsActivity) getActivity()).startPreferencePanel(
- SavedAccessPointsWifiSettings.class.getCanonicalName(), null,
- R.string.wifi_saved_access_points_titlebar, null, this, 0);
- } else {
- startFragment(this, SavedAccessPointsWifiSettings.class.getCanonicalName(),
- R.string.wifi_saved_access_points_titlebar,
- -1 /* Do not request a result */, null);
- }
- return true;
case MENU_ID_ADVANCED:
if (getActivity() instanceof SettingsActivity) {
((SettingsActivity) getActivity()).startPreferencePanel(
@@ -446,6 +428,18 @@
null);
}
return true;
+ case MENU_ID_CONFIGURE:
+ if (getActivity() instanceof SettingsActivity) {
+ ((SettingsActivity) getActivity()).startPreferencePanel(
+ ConfigureWifiSettings.class.getCanonicalName(), null,
+ R.string.wifi_configure_titlebar, null, this, 0);
+ } else {
+ startFragment(this, ConfigureWifiSettings.class.getCanonicalName(),
+ R.string.wifi_configure_titlebar, -1 /* Do not request a results */,
+ null);
+ }
+ return true;
+
}
return super.onOptionsItemSelected(item);
}
@@ -530,16 +524,14 @@
if (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_NONE &&
!mSelectedAccessPoint.isSaved() && !mSelectedAccessPoint.isActive()) {
mSelectedAccessPoint.generateOpenNetworkConfig();
- if (!savedNetworksExist) {
- savedNetworksExist = true;
- getActivity().invalidateOptionsMenu();
- }
connect(mSelectedAccessPoint.getConfig());
- } else if (mSelectedAccessPoint.isSaved()){
+ } else if (mSelectedAccessPoint.isSaved()) {
showDialog(mSelectedAccessPoint, WifiConfigUiBase.MODE_VIEW);
} else {
showDialog(mSelectedAccessPoint, WifiConfigUiBase.MODE_CONNECT);
}
+ } else if (preference == mAddPreference) {
+ onAddNetworkPressed();
} else {
return super.onPreferenceTreeClick(preference);
}
@@ -678,8 +670,23 @@
}
if (!hasAvailableAccessPoints) {
setProgressBarVisible(true);
- addMessagePreference(R.string.wifi_empty_list_wifi_on);
+ Preference pref = new Preference(getContext()) {
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ // Show a line on each side of add network.
+ holder.setDividerAllowedBelow(true);
+ }
+ };
+ pref.setSelectable(false);
+ pref.setSummary(R.string.wifi_empty_list_wifi_on);
+ pref.setOrder(0);
+ getPreferenceScreen().addPreference(pref);
+ mAddPreference.setOrder(1);
+ getPreferenceScreen().addPreference(mAddPreference);
} else {
+ mAddPreference.setOrder(index++);
+ getPreferenceScreen().addPreference(mAddPreference);
setProgressBarVisible(false);
}
break;
@@ -699,11 +706,6 @@
setProgressBarVisible(false);
break;
}
- // Update "Saved Networks" menu option.
- if (savedNetworksExist != mWifiTracker.doSavedNetworksExist()) {
- savedNetworksExist = !savedNetworksExist;
- getActivity().invalidateOptionsMenu();
- }
}
protected TextView initEmptyView() {
@@ -768,11 +770,6 @@
@Override
public void onWifiStateChanged(int state) {
- Activity activity = getActivity();
- if (activity != null) {
- activity.invalidateOptionsMenu();
- }
-
switch (state) {
case WifiManager.WIFI_STATE_ENABLING:
addMessagePreference(R.string.wifi_starting);
diff --git a/src/com/android/settings/wifi/WifiStatusTest.java b/src/com/android/settings/wifi/WifiStatusTest.java
index 38b3a15..4577496 100644
--- a/src/com/android/settings/wifi/WifiStatusTest.java
+++ b/src/com/android/settings/wifi/WifiStatusTest.java
@@ -148,8 +148,7 @@
mScanList = (TextView) findViewById(R.id.scan_list);
- mPingIpAddr = (TextView) findViewById(R.id.pingIpAddr);
- mPingHostname = (TextView) findViewById(R.id.pingHostname);
+ mPingHostname = (TextView) findViewById(R.id.pingHostnameV4);
mHttpClientTest = (TextView) findViewById(R.id.httpClientTest);
pingTestButton = (Button) findViewById(R.id.ping_test);
@@ -317,19 +316,10 @@
final Runnable updatePingResults = new Runnable() {
public void run() {
- mPingIpAddr.setText(mPingIpAddrResult);
mPingHostname.setText(mPingHostnameResult);
mHttpClientTest.setText(mHttpClientTestResult);
}
};
- Thread ipAddrThread = new Thread() {
- @Override
- public void run() {
- pingIpAddr();
- handler.post(updatePingResults);
- }
- };
- ipAddrThread.start();
Thread hostnameThread = new Thread() {
@Override
@@ -350,28 +340,6 @@
httpClientThread.start();
}
- /**
- * The ping functions have been borrowed from Radio diagnostic app to
- * enable quick access on the wifi status screen
- */
- private final void pingIpAddr() {
- try {
- // TODO: Hardcoded for now, make it UI configurable
- String ipAddress = "74.125.47.104";
- Process p = Runtime.getRuntime().exec("ping -c 1 -w 100 " + ipAddress);
- int status = p.waitFor();
- if (status == 0) {
- mPingIpAddrResult = "Pass";
- } else {
- mPingIpAddrResult = "Fail: IP addr not reachable";
- }
- } catch (IOException e) {
- mPingIpAddrResult = "Fail: IOException";
- } catch (InterruptedException e) {
- mPingIpAddrResult = "Fail: InterruptedException";
- }
- }
-
private final void pingHostname() {
try {
// TODO: Hardcoded for now, make it UI configurable
diff --git a/src/com/android/settings/wifi/p2p/WifiP2pPeer.java b/src/com/android/settings/wifi/p2p/WifiP2pPeer.java
index d4b50e6..a318e6f 100644
--- a/src/com/android/settings/wifi/p2p/WifiP2pPeer.java
+++ b/src/com/android/settings/wifi/p2p/WifiP2pPeer.java
@@ -23,7 +23,6 @@
import android.support.v7.preference.PreferenceViewHolder;
import android.text.TextUtils;
import android.widget.ImageView;
-
import com.android.settings.R;
public class WifiP2pPeer extends Preference {
@@ -41,15 +40,18 @@
device = dev;
setWidgetLayoutResource(R.layout.preference_widget_wifi_signal);
mRssi = 60; //TODO: fix
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder view) {
if (TextUtils.isEmpty(device.deviceName)) {
setTitle(device.deviceAddress);
} else {
setTitle(device.deviceName);
}
+ String[] statusArray = context.getResources().getStringArray(R.array.wifi_p2p_status);
+ setSummary(statusArray[device.status]);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder view) {
+ super.onBindViewHolder(view);
mSignal = (ImageView) view.findViewById(R.id.signal);
if (mRssi == Integer.MAX_VALUE) {
mSignal.setImageDrawable(null);
@@ -57,8 +59,7 @@
mSignal.setImageResource(R.drawable.wifi_signal_dark);
mSignal.setImageState(STATE_SECURED, true);
}
- refresh();
- super.onBindViewHolder(view);
+ mSignal.setImageLevel(getLevel());
}
@Override
@@ -87,14 +88,4 @@
}
return WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
}
-
- private void refresh() {
- if (mSignal == null) {
- return;
- }
- Context context = getContext();
- mSignal.setImageLevel(getLevel());
- String[] statusArray = context.getResources().getStringArray(R.array.wifi_p2p_status);
- setSummary(statusArray[device.status]);
- }
}