Merge "Remove VR features from apps"
diff --git a/Android.bp b/Android.bp
index 37ddf93..b5dfe79 100644
--- a/Android.bp
+++ b/Android.bp
@@ -55,7 +55,11 @@
],
srcs: ["src/**/*.java", "src/**/*.kt"],
- resource_dirs: ["res", "res-product"],
+ resource_dirs: [
+ "res",
+ "res-export", // for external usage
+ "res-product",
+ ],
static_libs: [
"androidx-constraintlayout_constraintlayout",
"androidx.slice_slice-builders",
diff --git a/res-export/.README.md b/res-export/.README.md
new file mode 100644
index 0000000..42b788e
--- /dev/null
+++ b/res-export/.README.md
@@ -0,0 +1,4 @@
+### Resources exported for external usage
+
+This folder contains the resources which is **not** used by Settings, but is
+exported for external usage by other apps.
diff --git a/res-export/drawable/ic_find_device_disabled.xml b/res-export/drawable/ic_find_device_disabled.xml
new file mode 100644
index 0000000..21e92c9
--- /dev/null
+++ b/res-export/drawable/ic_find_device_disabled.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFF44336"
+ android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13C19,5.13 15.87,2 12,2zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9zM11,13h2v2h-2V13zM13,6h-2v5h2V6z"/>
+</vector>
diff --git a/res-export/drawable/ic_find_device_enabled.xml b/res-export/drawable/ic_find_device_enabled.xml
new file mode 100644
index 0000000..614ac6d
--- /dev/null
+++ b/res-export/drawable/ic_find_device_enabled.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FF43A047"
+ android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13C19,5.13 15.87,2 12,2zM7,9c0,-2.76 2.24,-5 5,-5s5,2.24 5,5c0,2.88 -2.88,7.19 -5,9.88C9.92,16.21 7,11.85 7,9zM14.5,9c0,1.38 -1.12,2.5 -2.5,2.5S9.5,10.38 9.5,9s1.12,-2.5 2.5,-2.5S14.5,7.62 14.5,9z"/>
+</vector>
diff --git a/res-export/drawable/ic_ota_update_available.xml b/res-export/drawable/ic_ota_update_available.xml
new file mode 100644
index 0000000..58412a2
--- /dev/null
+++ b/res-export/drawable/ic_ota_update_available.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFD93025"
+ android:pathData="M17,1.01L7,1C5.9,1 5,1.9 5,3v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3C19,1.9 18.1,1.01 17,1.01zM17,21H7l0,-1h10V21zM17,18H7V6h10V18zM7,4V3h10v1H7zM16,12.5l-4,4l-4,-4l1.41,-1.41L11,12.67V8.5V8h2v0.5v4.17l1.59,-1.59L16,12.5z"/>
+</vector>
diff --git a/res-export/drawable/ic_ota_update_current.xml b/res-export/drawable/ic_ota_update_current.xml
new file mode 100644
index 0000000..7b80a23
--- /dev/null
+++ b/res-export/drawable/ic_ota_update_current.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FF1E8E3E"
+ android:pathData="M17,1.01L7,1C5.9,1 5,1.9 5,3v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3C19,1.9 18.1,1.01 17,1.01zM17,21H7l0,-1h10V21zM17,18H7V6h10V18zM7,4V3h10v1H7zM11.14,16l-3.84,-3.84l1.41,-1.42l2.43,2.42l4.16,-4.16l1.42,1.41L11.14,16z"/>
+</vector>
diff --git a/res-export/drawable/ic_ota_update_none.xml b/res-export/drawable/ic_ota_update_none.xml
new file mode 100644
index 0000000..0838ad3
--- /dev/null
+++ b/res-export/drawable/ic_ota_update_none.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFD93025"
+ android:pathData="M17,1.01L7,1C5.9,1 5,1.9 5,3v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3C19,1.9 18.1,1.01 17,1.01zM17,21H7l0,-1h10V21zM17,18H7V6h10V18zM7,4V3h10v1H7zM11,15h2v2h-2V15zM13,8h-2v5h2V8z"/>
+</vector>
diff --git a/res-export/drawable/ic_ota_update_stale.xml b/res-export/drawable/ic_ota_update_stale.xml
new file mode 100644
index 0000000..0838ad3
--- /dev/null
+++ b/res-export/drawable/ic_ota_update_stale.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFD93025"
+ android:pathData="M17,1.01L7,1C5.9,1 5,1.9 5,3v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3C19,1.9 18.1,1.01 17,1.01zM17,21H7l0,-1h10V21zM17,18H7V6h10V18zM7,4V3h10v1H7zM11,15h2v2h-2V15zM13,8h-2v5h2V8z"/>
+</vector>
diff --git a/res-export/drawable/ic_package_verifier_disabled.xml b/res-export/drawable/ic_package_verifier_disabled.xml
new file mode 100644
index 0000000..49fe0d3
--- /dev/null
+++ b/res-export/drawable/ic_package_verifier_disabled.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFEF6C00"
+ android:pathData="M12,4.24l6,3v4.1c0,3.9 -2.55,7.5 -6,8.59c-3.45,-1.09 -6,-4.7 -6,-8.59v-4.1L12,4.24M12,2L4,6v5.33c0,4.93 3.41,9.55 8,10.67c4.59,-1.12 8,-5.73 8,-10.67V6L12,2L12,2zM11,15h2v2h-2V15zM13,8h-2v5h2V8z"/>
+</vector>
diff --git a/res-export/drawable/ic_package_verifier_enabled.xml b/res-export/drawable/ic_package_verifier_enabled.xml
new file mode 100644
index 0000000..1e09eee
--- /dev/null
+++ b/res-export/drawable/ic_package_verifier_enabled.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FF43A047"
+ android:pathData="M11.14,16l-3.84,-3.84l1.41,-1.42l2.43,2.42l4.16,-4.16l1.42,1.41L11.14,16zM12,4.24l6,3v4.1c0,3.9 -2.55,7.5 -6,8.59c-3.45,-1.09 -6,-4.7 -6,-8.59v-4.1L12,4.24M12,2L4,6v5.33c0,4.93 3.41,9.55 8,10.67c4.59,-1.12 8,-5.73 8,-10.67V6L12,2L12,2z"/>
+</vector>
diff --git a/res-export/drawable/ic_partial_system_update_current.xml b/res-export/drawable/ic_partial_system_update_current.xml
new file mode 100644
index 0000000..6e16592
--- /dev/null
+++ b/res-export/drawable/ic_partial_system_update_current.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="24.0">
+<path
+ android:fillColor="#FF1E8E3E"
+ android:pathData="M17,18H7v-2.67l1.59,1.58L10,15.5l-3,-3l-1,-1l-4,4l1.41,1.42L5,15.33v4.17V20v1c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2v-7h-2V18zM17,21H7v-1h10V21z"/>
+<path
+ android:fillColor="#FF1E8E3E"
+ android:pathData="M7,6h10v2.67l-1.59,-1.58L14,8.5l4,4l4,-4l-1.41,-1.42L19,8.67V4.5V4V3c0,-1.1 -0.9,-1.99 -2,-1.99L7,1C5.9,1 5,1.9 5,3v7h2V6zM7,3h10v1H7V3z"/>
+</vector>
diff --git a/res-export/drawable/ic_partial_system_update_stale.xml b/res-export/drawable/ic_partial_system_update_stale.xml
new file mode 100644
index 0000000..905187c
--- /dev/null
+++ b/res-export/drawable/ic_partial_system_update_stale.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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="24.0">
+<path
+ android:fillColor="#FFD93025"
+ android:pathData="M17,18H7v-2.67l1.59,1.58L10,15.5l-3,-3l-1,-1l-4,4l1.41,1.42L5,15.33v4.17V20v1c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2v-7h-2V18zM17,21H7v-1h10V21z"/>
+<path
+ android:fillColor="#FFD93025"
+ android:pathData="M7,6h10v2.67l-1.59,-1.58L14,8.5l4,4l4,-4l-1.41,-1.42L19,8.67V4.5V4V3c0,-1.1 -0.9,-1.99 -2,-1.99L7,1C5.9,1 5,1.9 5,3v7h2V6zM7,3h10v1H7V3z"/>
+</vector>
diff --git a/res/values/bools.xml b/res-export/values/bools.xml
similarity index 100%
rename from res/values/bools.xml
rename to res-export/values/bools.xml
diff --git a/res/drawable-night/ic_battery_status_protected_24dp.xml b/res/drawable-night/ic_battery_status_protected_24dp.xml
deleted file mode 100644
index 23386cb..0000000
--- a/res/drawable-night/ic_battery_status_protected_24dp.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
- ~ Copyright (C) 2022 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT 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="vector"
- android:width="16dp"
- android:height="16dp"
- android:viewportWidth="16"
- android:viewportHeight="16">
- <path
- android:name="path_1"
- android:pathData="M 11.739 14.409 C 11.572 14.576 11.346 14.67 11.11 14.67 L 4.89 14.67 C 4.654 14.67 4.428 14.576 4.261 14.409 C 4.094 14.242 4 14.016 4 13.78 L 4 3.55 C 4 3.316 4.092 3.091 4.257 2.924 C 4.422 2.758 4.646 2.663 4.88 2.66 L 6.33 2.66 L 6.33 1.33 L 9.66 1.33 L 9.66 2.66 L 11.11 2.66 C 11.227 2.66 11.343 2.683 11.451 2.728 C 11.559 2.773 11.657 2.838 11.739 2.921 C 11.822 3.003 11.887 3.102 11.932 3.209 C 11.977 3.317 12 3.433 12 3.55 L 12 13.78 C 12 14.016 11.906 14.242 11.739 14.409 Z M 6 9 L 8.67 4 L 8.67 7.67 L 10 7.67 L 7.33 12.67 L 7.33 9 L 6 9 Z"
- android:fillColor="#ffffff"
- android:strokeWidth="1"
- android:fillType="evenOdd"/>
-</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_battery_dock_defender_untriggered_24dp.xml b/res/drawable/ic_battery_dock_defender_untriggered_24dp.xml
new file mode 100644
index 0000000..ba4d772
--- /dev/null
+++ b/res/drawable/ic_battery_dock_defender_untriggered_24dp.xml
@@ -0,0 +1,30 @@
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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="vector"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:name="path"
+ android:pathData="M 18 20.673 C 18 21.027 17.859 21.367 17.609 21.617 C 17.359 21.867 17.019 22.008 16.665 22.008 L 7.335 22.008 C 6.981 22.008 6.641 21.867 6.391 21.617 C 6.141 21.367 6 21.027 6 20.673 L 6 5.328 C 6 4.977 6.139 4.639 6.386 4.389 C 6.633 4.139 6.969 3.997 7.32 3.993 L 9.495 3.993 L 9.495 1.998 L 14.49 1.998 L 14.49 3.993 L 16.665 3.993 C 16.84 3.993 17.014 4.028 17.176 4.095 C 17.338 4.162 17.485 4.26 17.609 4.384 C 17.733 4.508 17.831 4.655 17.898 4.817 C 17.965 4.979 18 5.153 18 5.328 L 18 20.673 Z M 9 13.503 L 13.005 6.003 L 13.005 11.508 L 15 11.508 L 10.995 19.008 L 10.995 13.503 L 9 13.503 Z"
+ android:strokeWidth="1"
+ android:fillColor="?android:attr/colorAccent"
+ android:fillType="evenOdd"/>
+</vector>
diff --git a/res/drawable/ic_battery_status_protected_24dp.xml b/res/drawable/ic_battery_status_protected_24dp.xml
index 8841710..b4de02f 100644
--- a/res/drawable/ic_battery_status_protected_24dp.xml
+++ b/res/drawable/ic_battery_status_protected_24dp.xml
@@ -17,14 +17,18 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="vector"
- android:width="16dp"
- android:height="16dp"
- android:viewportWidth="16"
- android:viewportHeight="16">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
<path
android:name="path"
- android:pathData="M 11.739 14.409 C 11.572 14.576 11.346 14.67 11.11 14.67 L 4.89 14.67 C 4.654 14.67 4.428 14.576 4.261 14.409 C 4.094 14.242 4 14.016 4 13.78 L 4 3.55 C 4 3.316 4.092 3.091 4.257 2.924 C 4.422 2.758 4.646 2.663 4.88 2.66 L 6.33 2.66 L 6.33 1.33 L 9.66 1.33 L 9.66 2.66 L 11.11 2.66 C 11.227 2.66 11.343 2.683 11.451 2.728 C 11.559 2.773 11.657 2.838 11.739 2.921 C 11.822 3.003 11.887 3.102 11.932 3.209 C 11.977 3.317 12 3.433 12 3.55 L 12 13.78 C 12 14.016 11.906 14.242 11.739 14.409 Z M 6 9 L 8.67 4 L 8.67 7.67 L 10 7.67 L 7.33 12.67 L 7.33 9 L 6 9 Z"
- android:fillColor="#000000"
- android:strokeWidth="1"
- android:fillType="evenOdd"/>
-</vector>
\ No newline at end of file
+ android:pathData="M 12 11.493 L 18 9.243 L 18 5.328 C 18 4.593 17.4 3.993 16.665 3.993 L 14.49 3.993 L 14.49 1.998 L 9.495 1.998 L 9.495 3.993 L 7.32 3.993 C 6.585 3.993 5.985 4.593 5.985 5.328 L 5.985 20.673 C 5.985 21.408 6.585 22.008 7.32 22.008 L 13.365 22.008 C 12.495 20.583 12 18.918 12 17.193 L 12 11.493 Z M 7.995 6.003 L 15.99 6.003 L 15.99 9.003 L 7.995 9.003 L 7.995 6.003 Z"
+ android:fillColor="?android:attr/colorAccent"
+ android:strokeWidth="1"/>
+ <path
+ android:name="path_2"
+ android:pathData="M 19.005 10.998 L 14.01 12.873 L 14.01 17.178 C 14.01 20.328 16.14 23.283 19.005 24.003 C 21.87 23.283 24 20.343 24 17.178 L 24 12.873 L 19.005 10.998 Z"
+ android:fillColor="?android:attr/colorAccent"
+ android:strokeWidth="1"/>
+</vector>
diff --git a/res/layout/preference_expand_divider.xml b/res/layout/preference_expand_divider.xml
deleted file mode 100644
index 9b76688..0000000
--- a/res/layout/preference_expand_divider.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2021 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT 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/listPreferredItemHeightSmall"
- android:gravity="center_vertical"
- android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingRight="?android:attr/listPreferredItemPaddingRight"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:background="?android:attr/selectableItemBackground"
- android:orientation="horizontal">
-
- <TextView
- android:id="@+id/expand_title"
- android:layout_width="0px"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:paddingEnd="4dp"
- android:textAlignment="viewStart"
- style="@style/PreferenceCategoryTitleTextStyle"/>
-
- <ImageView
- android:id="@+id/expand_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_settings_expand_more"/>
-
-</LinearLayout>
diff --git a/res/layout/preference_tab.xml b/res/layout/preference_tab.xml
new file mode 100644
index 0000000..f9a7881
--- /dev/null
+++ b/res/layout/preference_tab.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT 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:theme="@style/Theme.TabTheme"
+ android:id="@+id/tab_container"
+ android:clipToPadding="true"
+ android:clipChildren="true"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <com.google.android.material.tabs.TabLayout
+ android:id="@+id/tabs"
+ style="@style/SettingsLibTabsStyle" />
+
+ <androidx.viewpager2.widget.ViewPager2
+ android:id="@+id/view_pager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0ff904d..fbae241 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -130,10 +130,30 @@
<string name="bluetooth_pair_other_ear_dialog_right_ear_positive_button">Pair right ear</string>
<!-- Connected devices settings. Positive button of the dialog to help user to pair left ear of the hearing aid device. Dialog shows when only one of the hearing aid device set is connected. [CHAR LIMIT=20] -->
<string name="bluetooth_pair_other_ear_dialog_left_ear_positive_button">Pair left ear</string>
-
+ <!-- Connected devices settings. Title of the preference to show the entrance of the hearing device controls page. [CHAR LIMIT=35] -->
+ <string name="bluetooth_device_controls_title">Hearing device controls</string>
+ <!-- Connected devices settings. Summary of the preference to show the entrance of the hearing device controls page. [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_device_controls_summary">Hearing device shortcut, hearing aid compatibility</string>
+ <!-- Connected devices settings. Title of the preference to show the entrance of the audio output page. It can change different types of audio are played on phone or other bluetooth devices. [CHAR LIMIT=35] -->
+ <string name="bluetooth_audio_routing_title">Audio output</string>
+ <!-- Connected devices settings. Summary of the preference to show the entrance of the audio output page. [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_audio_routing_summary">Choose whether different types of audio are played on your hearing device or phone speaker</string>
<!-- Title for related tools section. This section will list related tools below. [CHAR LIMIT=15] -->
<string name="bluetooth_screen_related">Related</string>
+ <!-- Bluetooth audio output settings. Title of the option managing ringtone audio path. [CHAR LIMIT=30] -->
+ <string name="bluetooth_ringtone_title">Ringtone</string>
+ <!-- Bluetooth audio output settings. Title of the option managing call audio path. [CHAR LIMIT=30] -->
+ <string name="bluetooth_call_title">Call</string>
+ <!-- Bluetooth audio output settings. Title of the option managing media audio path. [CHAR LIMIT=30] -->
+ <string name="bluetooth_media_title">Media</string>
+ <!-- Bluetooth audio output settings. Title of the option managing system sounds audio path. [CHAR LIMIT=30] -->
+ <string name="bluetooth_system_sounds_title">System sounds</string>
+ <!-- Bluetooth audio output settings. Title of the option to play audio on hearing aids. [CHAR LIMIT=40] -->
+ <string name="bluetooth_audio_path_hearing_device_title">Play on hearing device</string>
+ <!-- Bluetooth audio output settings. Title of the option to play audio on phone speaker. [CHAR LIMIT=40] -->
+ <string name="bluetooth_audio_path_phone_speaker_title">Play on phone speaker</string>
+
<!--Bluetooth settings screen, summary text for Bluetooth device with no name -->
<string name="bluetooth_device">Unnamed Bluetooth device</string>
<!--Bluetooth settings screen, text that appears in heading bar when scanning for devices -->
@@ -2697,6 +2717,16 @@
<!-- SD card & phone storage settings screen, message on screen after user selects Reset network settings [CHAR LIMIT=NONE] -->
<string name="reset_network_desc">This will reset all network settings, including:\n\n<li>Wi\u2011Fi</li>\n<li>Mobile data</li>\n<li>Bluetooth</li>"</string>
+ <!-- Reset Bluetooth and Wi-Fi Network -->
+ <!-- Dialog title to reset Bluetooth and Wi-Fi settings -->
+ <string name="reset_bluetooth_wifi_title">Reset Bluetooth & Wi\u2011Fi</string>
+ <!-- Dialog context when reset Bluetooth and Wi-Fi settings [CHAR LIMIT=NONE] -->
+ <string name="reset_bluetooth_wifi_desc">This will reset all Wi\u2011Fi & Bluetooth settings. You can\u2019t undo this action.</string>
+ <!-- Confirmation button text when reset Bluetooth and Wi-Fi settings [CHAR LIMIT=NONE] -->
+ <string name="reset_bluetooth_wifi_button_text">Reset</string>
+ <!-- Reset Bluetooth and Wi-Fi complete toast text [CHAR LIMIT=75] -->
+ <string name="reset_bluetooth_wifi_complete_toast">Bluetooth & Wi\u2011Fi have been reset</string>
+
<!-- Erase Euicc -->
<!-- Confirmation button of dialog to confirm resetting user's app preferences [CHAR LIMIT=NONE] -->
<string name="erase_euicc_data_button">Erase</string>
@@ -4211,8 +4241,8 @@
<!-- Button text for the accessibility dialog continue to the next screen for hearing aid. [CHAR LIMIT=32] -->
<string name="accessibility_hearingaid_instruction_continue_button">Continue</string>
- <!-- Title for the accessibility preference for hearing aid. [CHAR LIMIT=35] -->
- <string name="accessibility_hearingaid_title">Hearing aids</string>
+ <!-- Title for the accessibility preference for hearing devices. [CHAR LIMIT=35] -->
+ <string name="accessibility_hearingaid_title">Hearing devices</string>
<!-- Summary for the accessibility preference for hearing aid when not connected. [CHAR LIMIT=50] -->
<string name="accessibility_hearingaid_not_connected_summary">No hearing aids connected</string>
<!-- Summary for the accessibility preference for hearing aid when adding new devices. [CHAR LIMIT=50] -->
@@ -4231,6 +4261,29 @@
<string name="accessibility_hearingaid_left_and_right_side_device_summary"><xliff:g id="device_name" example="GN Hearing Aids">%1$s</xliff:g>, left and right</string>
<!-- Summary for the accessibility preference for hearing aid when there are more than one set of devices are active. [CHAR LIMIT=50] -->
<string name="accessibility_hearingaid_more_device_summary"><xliff:g id="device_name" example="GN Hearing Aids">%1$s</xliff:g> +1 more</string>
+ <!-- Title for the hearing device pairing preference. [CHAR LIMIT=20] -->
+ <string name="accessibility_hearing_device_pairing_title">Pair new device</string>
+ <!-- Title for the preference category containing the connected hearing device group. [CHAR LIMIT=20]-->
+ <string name="accessibility_hearing_device_saved_title">Saved devices</string>
+ <!-- Title for the preference category containing the controls of the hearing device. [CHAR LIMIT=35] -->
+ <string name="accessibility_hearing_device_control">Hearing device controls</string>
+ <!-- Title for the accessibility preference for hearing devices. [CHAR LIMIT=35] -->
+ <string name="accessibility_hearing_device_shortcut_title">Hearing device shortcut</string>
+ <!-- Title for the Hearing Aid Compatibility preference in the accessibility page. [CHAR LIMIT=35] -->
+ <string name="accessibility_hac_mode_title">Hearing aid compatibility</string>
+ <!--Summary for the Hearing Aid Compatibility preference in the accessibility page. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_hac_mode_summary">Improve audio for some hearing devices</string>
+ <!-- Description for text in accessibility hearing aids footer. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_hearing_device_footer_summary">Make sure your hearing devices are turned on and in pairing mode</string>
+ <!-- Title for the pair hearing device page. [CHAR LIMIT=25] -->
+ <string name="accessibility_hearing_device_pairing_page_title">Pair hearing device</string>
+ <!-- Title for the preference category containing the list of the available hearing during and after bluetooth scanning devices. [CHAR LIMIT=30] -->
+ <string name="accessibility_found_hearing_devices">Available devices</string>
+ <!-- Title for the preference category containing the all bluetooth devices during and after bluetooth scanning devices. Used when people can not find their hearing device in hearing device pairing list. [CHAR LIMIT=45] -->
+ <string name="accessibility_found_all_devices">Don\u2019t see your hearing device?</string>
+ <!-- Title for listing all bluetooth devices preference in the accessibility page. [CHAR LIMIT=40] -->
+ <string name="accessibility_list_all_devices_title">View all Bluetooth devices</string>
+
<!-- Title for the accessibility audio adjustment page. [CHAR LIMIT=50] -->
<string name="accessibility_audio_adjustment_title">Audio adjustment</string>
<!-- Title for control audio description preference. [CHAR LIMIT=50] -->
@@ -4987,12 +5040,22 @@
<string name="battery_usage_for_background_time">Background: <xliff:g id="time">%s</xliff:g></string>
<!-- [CHAR_LIMIT=NONE] Battery usage main screen footer for empty content -->
<string name="battery_usage_screen_footer_empty">Battery usage data will be available in a few hours once fully charged</string>
+ <!-- [CHAR_LIMIT=NONE] Battery chart label for the current time. -->
+ <string name="battery_usage_chart_label_now">now</string>
<!-- [CHAR_LIMIT=NONE] Accessibility content description for battery chart view. -->
<string name="battery_usage_chart">Battery usage chart</string>
<!-- [CHAR_LIMIT=NONE] Accessibility content description for daily battery chart view. -->
<string name="daily_battery_usage_chart">Daily battery usage chart</string>
<!-- [CHAR_LIMIT=NONE] Accessibility content description for hourly battery chart view. -->
<string name="hourly_battery_usage_chart">Hourly battery usage chart</string>
+ <!-- [CHAR_LIMIT=NONE] Battery usage breakdown title since last full charge -->
+ <string name="battery_usage_breakdown_title_since_last_full_charge">Usage proportional breakdown since last full charge</string>
+ <!-- [CHAR_LIMIT=NONE] Battery usage breakdown title for a selected slot -->
+ <string name="battery_usage_breakdown_title_for_slot">Usage proportional breakdown for <xliff:g id="slot">%s</xliff:g></string>
+ <!-- [CHAR_LIMIT=NONE] The tab title in the battery usage breakdown. -->
+ <string name="battery_usage_app_tab">App</string>
+ <!-- [CHAR_LIMIT=NONE] The tab title in the battery usage breakdown. -->
+ <string name="battery_usage_system_tab">System</string>
<!-- Process Stats strings -->
<skip />
@@ -8034,37 +8097,40 @@
<!-- [CHAR LIMIT=NONE] eSim deletion confirmation description -->
<string name="confirm_sim_deletion_description">Verify it\u0027s you before erasing a eSIM</string>
- <!-- TODO(b/258550150): Finalize all strings in this section and remove translatable="false" -->
<!-- [CHAR LIMIT=32] Name of Advanced memory protection page in "More Security Settings" and heading of page. -->
- <string name="memtag_title" translatable="false">Advanced memory protection beta</string>
+ <string name="memtag_title">Advanced memory protection beta</string>
<!-- [CHAR LIMIT=52] Label for button to turn on / off Advanced memory protection.-->
- <string name="memtag_toggle" translatable="false">Advanced memory protection</string>
+ <string name="memtag_toggle">Advanced memory protection</string>
<!-- [CHAR LIMIT=NONE] Subtitle of Advanced memory protection page. -->
- <string name="memtag_intro" translatable="false">This beta feature helps you protect your device from bugs that may put your security at risk.</string>
+ <string name="memtag_intro">This beta feature helps you protect your device from bugs that may put your security at risk.</string>
<!-- [CHAR LIMIT=NONE] Status label indicating that Advanced memory protection is on. -->
- <string name="memtag_on" translatable="false">On</string>
+ <string name="memtag_on">On</string>
<!-- [CHAR LIMIT=37] Status label indicating that Advanced memory protection is off. -->
- <string name="memtag_off" translatable="false">Off</string>
+ <string name="memtag_off">Off</string>
<!-- [CHAR LIMIT=37] Status label indicating that system needs to be rebooted for Advanced memory protection to be on. -->
- <string name="memtag_on_pending" translatable="false">On after restart</string>
+ <string name="memtag_on_pending">On after restart</string>
<!-- [CHAR LIMIT=37] Status label indicating that system needs to be rebooted for Advanced memory protection to be off. -->
- <string name="memtag_off_pending" translatable="false">Off after restart</string>
+ <string name="memtag_off_pending">Off after restart</string>
<!-- [CHAR LIMIT=37] Status label indicating that Advanced memory protection was forced off via remote device configuration. -->
- <string name="memtag_force_off" translatable="false">Currently unavailable for your device.</string>
+ <string name="memtag_force_off">Currently unavailable for your device</string>
+ <!-- [CHAR LIMIT=37] Status label indicating that Advanced memory protection was forced on via remote device configuration. -->
+ <string name="memtag_force_on">Always on for your device</string>
<!-- [CHAR LIMIT=NONE] Subtext on page to control Advanced memory protection settings. -->
- <string name="memtag_footer" translatable="false">You\u0027ll have to restart your device to turn Advanced memory protection on or off. When it\u0027s on, you may notice slower device performance.</string>
+ <string name="memtag_footer">You\u0027ll have to restart your device to turn Advanced memory protection on or off. When it\u0027s on, you may notice slower device performance.</string>
<!-- [CHAR LIMIT=31] Header of dialog asking user to reboot device. -->
- <string name="memtag_reboot_title" translatable="false">Restart device?</string>
+ <string name="memtag_reboot_title">Restart device?</string>
<!-- [CHAR LIMIT=NONE] Message shown in dialog prompting user to reboot device to turn on Advanced memory protection.-->
- <string name="memtag_reboot_message_on" translatable="false">You\u0027ll need to restart your device to turn on Advanced memory protection.</string>
+ <string name="memtag_reboot_message_on">You\u0027ll need to restart your device to turn on Advanced memory protection.</string>
<!-- [CHAR LIMIT=NONE] Message shown in dialog prompting user to reboot device to turn off Advanced memory protection.-->
- <string name="memtag_reboot_message_off" translatable="false">You\u0027ll need to restart your device to turn off Advanced memory protection.</string>
+ <string name="memtag_reboot_message_off">You\u0027ll need to restart your device to turn off Advanced memory protection.</string>
<!-- [CHAR LIMIT=17] Button label in dialog prompting user to reboot device.-->
- <string name="memtag_reboot_yes" translatable="false">Restart</string>
+ <string name="memtag_reboot_yes">Restart</string>
<!-- [CHAR LIMIT=17] Button label in dialog prompting user to reboot device.-->
- <string name="memtag_reboot_no" translatable="false">Not now</string>
+ <string name="memtag_reboot_no">Not now</string>
<!-- [CHAR LIMIT=NONE] Label for Learn More link. -->
- <string name="memtag_learn_more" translatable="false">Learn more about Advanced memory protection.</string>
+ <string name="memtag_learn_more">Learn more about Advanced memory protection.</string>
+ <!-- [CHAR LIMIT=NONE] Search keywords for Advanced memory protection option. -->
+ <string name="keywords_memtag" translatable="false">MTE, Memory Tagging Extension</string>
<!-- Opening string on the dialog that prompts the user to confirm that they really want to delete their existing work profile. The administration app icon and name appear after the final colon. [CHAR LIMIT=NONE] -->
<string name="opening_paragraph_delete_profile_unknown_company">This work profile is managed by:</string>
@@ -10652,8 +10718,8 @@
<string name="lockscreen_double_line_clock_summary">Show double-line clock when available</string>
<!-- Lockscreen double-line clock toggle [CHAR LIMIT=60] -->
<string name="lockscreen_double_line_clock_setting_toggle">Double-line clock</string>
- <!-- Lock screen buttons preference [CHAR LIMIT=60] -->
- <string name="lockscreen_quick_affordances_title">Buttons</string>
+ <!-- Lock screen shortcuts preference [CHAR LIMIT=60] -->
+ <string name="lockscreen_quick_affordances_title">Shortcuts</string>
<!-- Summary for the lock screen button preference [CHAR LIMIT=60] -->
<plurals name="lockscreen_quick_affordances_summary">
<item quantity="zero">None</item>
diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml
index 981afb3..a4b5faa 100644
--- a/res/xml/network_provider_internet.xml
+++ b/res/xml/network_provider_internet.xml
@@ -42,7 +42,7 @@
settings:keywords="@string/calls_and_sms"
settings:useAdminDisabledSummary="true" />
- <com.android.settings.widget.AddPreference
+ <com.android.settingslib.RestrictedPreference
android:key="mobile_network_list"
android:title="@string/provider_network_settings_title"
android:summary="@string/summary_placeholder"
diff --git a/res/xml/power_usage_advanced.xml b/res/xml/power_usage_advanced.xml
index e9274ce..4371995 100644
--- a/res/xml/power_usage_advanced.xml
+++ b/res/xml/power_usage_advanced.xml
@@ -22,14 +22,30 @@
settings:keywords="@string/keywords_battery_usage">
<com.android.settings.fuelgauge.batteryusage.BatteryHistoryPreference
- android:key="battery_graph"/>
+ android:key="battery_chart"
+ settings:controller=
+ "com.android.settings.fuelgauge.batteryusage.BatteryChartPreferenceController" />
<PreferenceCategory
- android:key="app_list"/>
+ android:key="battery_usage_breakdown"
+ settings:controller=
+ "com.android.settings.fuelgauge.batteryusage.BatteryUsageBreakdownController"
+ settings:isPreferenceVisible="false">
- <com.android.settingslib.widget.FooterPreference
- android:key="battery_graph_footer"
- android:title="@string/battery_usage_screen_footer"
- android:selectable="false"
- settings:searchable="false"/>
+ <com.android.settings.fuelgauge.batteryusage.TabPreference
+ android:key="battery_usage_tab"
+ settings:isPreferenceVisible="false" />
+
+ <PreferenceCategory
+ android:key="app_list"
+ settings:isPreferenceVisible="false" />
+
+ <com.android.settingslib.widget.FooterPreference
+ android:key="battery_usage_footer"
+ android:selectable="false"
+ android:title="@string/battery_usage_screen_footer"
+ settings:isPreferenceVisible="false"
+ settings:searchable="false" />
+
+ </PreferenceCategory>
</PreferenceScreen>
diff --git a/res/xml/reset_dashboard_fragment.xml b/res/xml/reset_dashboard_fragment.xml
index 25161a5..5502558 100644
--- a/res/xml/reset_dashboard_fragment.xml
+++ b/res/xml/reset_dashboard_fragment.xml
@@ -26,8 +26,17 @@
android:title="@string/reset_network_title"
settings:userRestriction="no_network_reset"
settings:useAdminDisabledSummary="true"
+ settings:isPreferenceVisible="@bool/config_show_sim_info"
android:fragment="com.android.settings.ResetNetwork" />
+ <!-- Bluetooth and WiFi reset -->
+ <com.android.settingslib.RestrictedPreference
+ android:key="network_reset_bluetooth_wifi_pref"
+ android:title="@string/reset_bluetooth_wifi_title"
+ settings:userRestriction="no_network_reset"
+ settings:useAdminDisabledSummary="true"
+ settings:controller="com.android.settings.network.BluetoothWiFiResetPreferenceController" />
+
<!-- Reset app preferences -->
<Preference
android:key="reset_app_prefs"
diff --git a/res/xml/security_advanced_settings.xml b/res/xml/security_advanced_settings.xml
index c8ed6db..c489597 100644
--- a/res/xml/security_advanced_settings.xml
+++ b/res/xml/security_advanced_settings.xml
@@ -112,6 +112,7 @@
android:id="@+id/memtag_page"
android:key="memtag_page"
android:title="@string/memtag_title"
+ settings:keywords="@string/keywords_memtag"
android:fragment="com.android.settings.security.MemtagPage"
settings:controller="com.android.settings.security.MemtagPagePreferenceController" />
diff --git a/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java b/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java
index 893837c..d1614ca 100644
--- a/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java
@@ -64,7 +64,12 @@
static final String RESET_KEY = "reset";
private static final String PREVIEW_KEY = "preview";
private static final String NEED_RESET_SETTINGS = "need_reset_settings";
+ private static final String LAST_PREVIEW_INDEX = "last_preview_index";
+ private static final int UNKNOWN_INDEX = -1;
+
private FontWeightAdjustmentPreferenceController mFontWeightAdjustmentController;
+ private TextReadingPreviewController mPreviewController;
+ private int mLastPreviewIndex = UNKNOWN_INDEX;
private int mEntryPoint = EntryPoint.UNKNOWN_ENTRY;
/**
@@ -95,14 +100,20 @@
boolean mNeedResetSettings;
@Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
mNeedResetSettings = false;
mResetStateListeners = getResetStateListeners();
- if (icicle != null && icicle.getBoolean(NEED_RESET_SETTINGS)) {
- mResetStateListeners.forEach(ResetStateListener::resetState);
+ if (savedInstanceState != null) {
+ if (savedInstanceState.getBoolean(NEED_RESET_SETTINGS)) {
+ mResetStateListeners.forEach(ResetStateListener::resetState);
+ }
+
+ if (savedInstanceState.containsKey(LAST_PREVIEW_INDEX)) {
+ mLastPreviewIndex = savedInstanceState.getInt(LAST_PREVIEW_INDEX);
+ }
}
}
@@ -139,19 +150,19 @@
final FontSizeData fontSizeData = new FontSizeData(context);
final DisplaySizeData displaySizeData = createDisplaySizeData(context);
- final TextReadingPreviewController previewController = new TextReadingPreviewController(
- context, PREVIEW_KEY, fontSizeData, displaySizeData);
- previewController.setEntryPoint(mEntryPoint);
- controllers.add(previewController);
+ mPreviewController = new TextReadingPreviewController(context, PREVIEW_KEY, fontSizeData,
+ displaySizeData);
+ mPreviewController.setEntryPoint(mEntryPoint);
+ controllers.add(mPreviewController);
final PreviewSizeSeekBarController fontSizeController = new PreviewSizeSeekBarController(
context, FONT_SIZE_KEY, fontSizeData);
- fontSizeController.setInteractionListener(previewController);
+ fontSizeController.setInteractionListener(mPreviewController);
controllers.add(fontSizeController);
final PreviewSizeSeekBarController displaySizeController = new PreviewSizeSeekBarController(
context, DISPLAY_SIZE_KEY, displaySizeData);
- displaySizeController.setInteractionListener(previewController);
+ displaySizeController.setInteractionListener(mPreviewController);
controllers.add(displaySizeController);
mFontWeightAdjustmentController =
@@ -206,6 +217,17 @@
if (mNeedResetSettings) {
outState.putBoolean(NEED_RESET_SETTINGS, true);
}
+
+ outState.putInt(LAST_PREVIEW_INDEX, mPreviewController.getCurrentItem());
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ if (mLastPreviewIndex != UNKNOWN_INDEX) {
+ mPreviewController.setCurrentItem(mLastPreviewIndex);
+ }
}
@VisibleForTesting
diff --git a/src/com/android/settings/accessibility/TextReadingPreviewController.java b/src/com/android/settings/accessibility/TextReadingPreviewController.java
index 29faaaa..8fa8dc7 100644
--- a/src/com/android/settings/accessibility/TextReadingPreviewController.java
+++ b/src/com/android/settings/accessibility/TextReadingPreviewController.java
@@ -133,6 +133,14 @@
postCommitDelayed(CHANGE_BY_SEEKBAR_DELAY_MS);
}
+ void setCurrentItem(int index) {
+ mPreviewPreference.setCurrentItem(index);
+ }
+
+ int getCurrentItem() {
+ return mPreviewPreference.getCurrentItem();
+ }
+
/**
* The entry point is used for logging.
*
diff --git a/src/com/android/settings/accessibility/TextReadingPreviewPreference.java b/src/com/android/settings/accessibility/TextReadingPreviewPreference.java
index 4b8ca39..cef6f25 100644
--- a/src/com/android/settings/accessibility/TextReadingPreviewPreference.java
+++ b/src/com/android/settings/accessibility/TextReadingPreviewPreference.java
@@ -37,6 +37,24 @@
private int mLastLayerIndex;
private PreviewPagerAdapter mPreviewAdapter;
+ private final ViewPager.OnPageChangeListener mPageChangeListener =
+ new ViewPager.OnPageChangeListener() {
+ @Override
+ public void onPageScrolled(int i, float v, int i1) {
+ // Do nothing
+ }
+
+ @Override
+ public void onPageSelected(int i) {
+ mCurrentItem = i;
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int i) {
+ // Do nothing
+ }
+ };
+
TextReadingPreviewPreference(Context context) {
super(context);
init();
@@ -63,6 +81,7 @@
super.onBindViewHolder(holder);
final ViewPager viewPager = (ViewPager) holder.findViewById(R.id.preview_pager);
+ viewPager.addOnPageChangeListener(mPageChangeListener);
final DotsPageIndicator pageIndicator =
(DotsPageIndicator) holder.findViewById(R.id.page_indicator);
updateAdapterIfNeeded(viewPager, pageIndicator, mPreviewAdapter);
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingService.java b/src/com/android/settings/bluetooth/BluetoothPairingService.java
index 9883e61..d8487e4 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingService.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingService.java
@@ -99,11 +99,8 @@
Log.d(TAG, "Notification cancel " + " (" +
mDevice.getName() + ")");
mDevice.cancelBondProcess();
- } else {
- int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
- BluetoothDevice.ERROR);
- Log.d(TAG, "Dismiss pairing for " + " (" +
- mDevice.getName() + "), BondState: " + bondState);
+ } else { // BluetoothDevice.ACTION_PAIRING_CANCEL
+ Log.d(TAG, "Dismiss pairing for " + " (" + mDevice.getName() + ")");
}
mNm.cancel(NOTIFICATION_ID);
diff --git a/src/com/android/settings/connecteddevice/stylus/StylusDevicesController.java b/src/com/android/settings/connecteddevice/stylus/StylusDevicesController.java
index 0081d87..bf2fdda 100644
--- a/src/com/android/settings/connecteddevice/stylus/StylusDevicesController.java
+++ b/src/com/android/settings/connecteddevice/stylus/StylusDevicesController.java
@@ -22,6 +22,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.provider.Settings;
+import android.provider.Settings.Secure;
import android.util.Log;
import android.view.InputDevice;
@@ -125,6 +126,8 @@
pref.setTitle(mContext.getString(R.string.stylus_ignore_button));
pref.setIcon(R.drawable.ic_block);
pref.setOnPreferenceClickListener(this);
+ pref.setChecked(Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.STYLUS_BUTTONS_DISABLED, 0) == 1);
return pref;
}
@@ -147,7 +150,9 @@
((SwitchPreference) preference).isChecked() ? 1 : 0);
break;
case KEY_IGNORE_BUTTON:
- // TODO(b/251199452): to turn off stylus button presses
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Secure.STYLUS_BUTTONS_DISABLED,
+ ((SwitchPreference) preference).isChecked() ? 1 : 0);
break;
}
return true;
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectRecentLocationRequestFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectRecentLocationRequestFragment.java
deleted file mode 100644
index 16cb43c..0000000
--- a/src/com/android/settings/dashboard/profileselector/ProfileSelectRecentLocationRequestFragment.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.profileselector;
-
-import android.os.Bundle;
-
-import androidx.fragment.app.Fragment;
-
-import com.android.settings.R;
-import com.android.settings.location.RecentLocationRequestSeeAllFragment;
-
-/**
- * Recent location request page for personal/managed profile.
- */
-public class ProfileSelectRecentLocationRequestFragment extends ProfileSelectFragment {
-
- @Override
- public Fragment[] getFragments() {
- final Bundle workOnly = new Bundle();
- workOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.WORK);
- final Fragment workFragment = new RecentLocationRequestSeeAllFragment();
- workFragment.setArguments(workOnly);
-
- final Bundle personalOnly = new Bundle();
- personalOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.PERSONAL);
- final Fragment personalFragment = new RecentLocationRequestSeeAllFragment();
- personalFragment.setArguments(personalOnly);
- return new Fragment[]{
- personalFragment, //0
- workFragment
- };
- }
-
- @Override
- protected int getPreferenceScreenResId() {
- return R.xml.location_recent_requests_header;
- }
-}
diff --git a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
index 128ceca..691cbd6 100644
--- a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
+++ b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
@@ -41,6 +41,7 @@
import com.android.settings.deviceinfo.WifiMacAddressPreferenceController;
import com.android.settings.deviceinfo.imei.ImeiInfoPreferenceController;
import com.android.settings.deviceinfo.simstatus.SimStatusPreferenceController;
+import com.android.settings.deviceinfo.simstatus.SlotSimStatus;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -50,6 +51,8 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
@SearchIndexable
public class MyDeviceInfoFragment extends DashboardFragment
@@ -104,16 +107,9 @@
Context context, MyDeviceInfoFragment fragment, Lifecycle lifecycle) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
- String simStatusKey = SimStatusPreferenceController.KEY_SIM_STATUS;
- SimStatusPreferenceController defaultRecord =
- new SimStatusPreferenceController(context, simStatusKey);
-
- for (int slotIndex = 0; slotIndex < defaultRecord.getSimSlotSize(); slotIndex ++) {
- SimStatusPreferenceController slotRecord =
- new SimStatusPreferenceController(context, simStatusKey + slotIndex + 1);
- slotRecord.init(fragment, slotIndex);
- controllers.add(slotRecord);
- }
+ final ExecutorService executor = (fragment == null) ? null :
+ Executors.newSingleThreadExecutor();
+ final SlotSimStatus slotSimStatus = new SlotSimStatus(context, executor);
controllers.add(new IpAddressPreferenceController(context, lifecycle));
controllers.add(new WifiMacAddressPreferenceController(context, lifecycle));
@@ -124,6 +120,17 @@
controllers.add(new FeedbackPreferenceController(fragment, context));
controllers.add(new FccEquipmentIdPreferenceController(context));
controllers.add(new UptimePreferenceController(context, lifecycle));
+
+ for (int slotIndex = 0; slotIndex < slotSimStatus.size(); slotIndex ++) {
+ SimStatusPreferenceController slotRecord =
+ new SimStatusPreferenceController(context,
+ slotSimStatus.getPreferenceKey(slotIndex));
+ slotRecord.init(fragment, slotSimStatus);
+ controllers.add(slotRecord);
+ }
+ if (executor != null) {
+ executor.shutdown();
+ }
return controllers;
}
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java
index 529d314..b75853d 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java
@@ -19,7 +19,6 @@
import android.content.Context;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
import android.os.UserManager;
import androidx.annotation.VisibleForTesting;
@@ -38,39 +37,28 @@
public class SimStatusPreferenceController extends BasePreferenceController {
- public static final String KEY_SIM_STATUS = "sim_status";
private static final String KEY_PREFERENCE_CATEGORY = "device_detail_category";
- private final TelephonyManager mTelephonyManager;
private final SubscriptionManager mSubscriptionManager;
private final List<Preference> mPreferenceList = new ArrayList<>();
private Fragment mFragment;
- private int mSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+ private SlotSimStatus mSlotSimStatus;
public SimStatusPreferenceController(Context context, String prefKey) {
super(context, prefKey);
- mTelephonyManager = context.getSystemService(TelephonyManager.class);
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
}
/**
* Initialize this preference controller.
* @param fragment parent fragment
- * @param slotIndex index of slot
+ * @param slotSimStatus SlotSimStatus object
*/
- public void init(Fragment fragment, int slotIndex) {
+ public void init(Fragment fragment, SlotSimStatus slotSimStatus) {
mFragment = fragment;
- mSlotIndex = slotIndex;
- }
-
- /**
- * Get number of subscription slots.
- * @return number of slots
- */
- public int getSimSlotSize() {
- return isAvailable() ? mTelephonyManager.getPhoneCount() : 0;
+ mSlotSimStatus = slotSimStatus;
}
/**
@@ -78,7 +66,8 @@
* @return index of slot
*/
public int getSimSlotIndex() {
- return mSlotIndex;
+ return mSlotSimStatus == null ? SubscriptionManager.INVALID_SIM_SLOT_INDEX :
+ mSlotSimStatus.findSlotIndexByKey(getPreferenceKey());
}
@Override
@@ -95,26 +84,27 @@
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- if (!SubscriptionUtil.isSimHardwareVisible(mContext)) {
+ if ((!SubscriptionUtil.isSimHardwareVisible(mContext)) || (mSlotSimStatus == null)) {
return;
}
- final Preference preference = screen.findPreference(KEY_SIM_STATUS);
+ String basePreferenceKey = mSlotSimStatus.getPreferenceKey(
+ SubscriptionManager.INVALID_SIM_SLOT_INDEX);
+ final Preference preference = screen.findPreference(basePreferenceKey);
if (!isAvailable() || preference == null || !preference.isVisible()) {
return;
}
final PreferenceCategory category = screen.findPreference(KEY_PREFERENCE_CATEGORY);
- final int simStatusOrder = preference.getOrder();
+ mSlotSimStatus.setBasePreferenceOrdering(preference.getOrder());
screen.removePreference(preference);
preference.setVisible(false);
// Add additional preferences for each sim in the device
- for (int simSlotNumber = 0; simSlotNumber < mTelephonyManager.getPhoneCount();
- simSlotNumber++) {
+ for (int simSlotNumber = 0; simSlotNumber < mSlotSimStatus.size(); simSlotNumber++) {
final Preference multiSimPreference = createNewPreference(screen.getContext());
multiSimPreference.setCopyingEnabled(true);
- multiSimPreference.setOrder(simStatusOrder + simSlotNumber + 1);
- multiSimPreference.setKey(KEY_SIM_STATUS + simSlotNumber + 1);
+ multiSimPreference.setOrder(mSlotSimStatus.getPreferenceOrdering(simSlotNumber));
+ multiSimPreference.setKey(mSlotSimStatus.getPreferenceKey(simSlotNumber));
category.addPreference(multiSimPreference);
mPreferenceList.add(multiSimPreference);
}
@@ -141,22 +131,28 @@
}
private String getPreferenceTitle(int simSlot) {
- return mTelephonyManager.getPhoneCount() > 1 ? mContext.getString(
+ return mSlotSimStatus.size() > 1 ? mContext.getString(
R.string.sim_status_title_sim_slot, simSlot + 1) : mContext.getString(
R.string.sim_status_title);
}
- private CharSequence getCarrierName(int simSlot) {
+ private SubscriptionInfo getSubscriptionInfo(int simSlot) {
final List<SubscriptionInfo> subscriptionInfoList =
mSubscriptionManager.getActiveSubscriptionInfoList();
if (subscriptionInfoList != null) {
for (SubscriptionInfo info : subscriptionInfoList) {
if (info.getSimSlotIndex() == simSlot) {
- return info.getCarrierName();
+ return info;
}
}
}
- return mContext.getText(R.string.device_info_not_available);
+ return null;
+ }
+
+ private CharSequence getCarrierName(int simSlot) {
+ SubscriptionInfo subInfo = getSubscriptionInfo(simSlot);
+ return (subInfo != null) ? subInfo.getCarrierName() :
+ mContext.getText(R.string.device_info_not_available);
}
@VisibleForTesting
diff --git a/src/com/android/settings/deviceinfo/simstatus/SlotSimStatus.java b/src/com/android/settings/deviceinfo/simstatus/SlotSimStatus.java
new file mode 100644
index 0000000..033222a
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/simstatus/SlotSimStatus.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.deviceinfo.simstatus;
+
+import android.content.Context;
+import android.telephony.TelephonyManager;
+import android.telephony.SubscriptionManager;
+import android.util.Log;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Phaser;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * A class for showing a summary of status of sim slots.
+ */
+public class SlotSimStatus {
+
+ private static final String TAG = "SlotSimStatus";
+
+ private final AtomicInteger mNumberOfSlots = new AtomicInteger(0);
+ private final Phaser mBlocker = new Phaser(1);
+ private int mBasePreferenceOrdering;
+
+ private static final String KEY_SIM_STATUS = "sim_status";
+
+ /**
+ * Construct of class.
+ * @param context Context
+ */
+ public SlotSimStatus(Context context) {
+ this(context, null);
+ }
+
+ /**
+ * Construct of class.
+ * @param context Context
+ * @param executor executor for offload to thread
+ */
+ public SlotSimStatus(Context context, Executor executor) {
+ if (executor == null) {
+ queryRecords(context);
+ } else {
+ executor.execute(() -> queryRecords(context));
+ }
+ }
+
+ protected void queryRecords(Context context) {
+ TelephonyManager telMgr = context.getSystemService(TelephonyManager.class);
+ if (telMgr != null) {
+ mNumberOfSlots.set(telMgr.getPhoneCount());
+ }
+ mBlocker.arrive();
+ }
+
+ protected void waitForResult() {
+ mBlocker.awaitAdvance(0);
+ }
+
+ /**
+ * Set base ordering of Preference.
+ * @param baseOrdering the base ordering for SIM Status within "About Phone".
+ */
+ public void setBasePreferenceOrdering(int baseOrdering) {
+ mBasePreferenceOrdering = baseOrdering;
+ }
+
+ /**
+ * Number of slots available.
+ * @return number of slots
+ */
+ public int size() {
+ waitForResult();
+ return mNumberOfSlots.get();
+ }
+
+ /**
+ * Get ordering of Preference based on index of slot.
+ * @param slotIndex index of slot
+ * @return Preference ordering.
+ */
+ public int getPreferenceOrdering(int slotIndex) {
+ return mBasePreferenceOrdering + 1 + slotIndex;
+ }
+
+ /**
+ * Get key of Preference and PreferenceController based on index of slot.
+ * @param slotIndex index of slot
+ * @return Preference key.
+ */
+ public String getPreferenceKey(int slotIndex) {
+ if (slotIndex == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ return KEY_SIM_STATUS;
+ }
+ return KEY_SIM_STATUS + (1 + slotIndex);
+ }
+
+ /**
+ * Get slot index based on Preference key
+ * @param prefKey is the preference key
+ * @return slot index.
+ */
+ public int findSlotIndexByKey(String prefKey) {
+ int simSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX + 1;
+ try {
+ simSlotIndex = Integer.parseInt(prefKey.substring(KEY_SIM_STATUS.length()));
+ } catch (Exception exception) {
+ Log.w(TAG, "Preference key invalid: " + prefKey +
+ ". Error Msg: " + exception.getMessage());
+ }
+ return simSlotIndex - 1;
+ }
+}
diff --git a/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceController.java b/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceController.java
index 94f1519..2c06a51 100644
--- a/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceController.java
+++ b/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceController.java
@@ -50,13 +50,13 @@
final Preference preference = screen.findPreference(getPreferenceKey());
if (preference != null) {
preference.setOnPreferenceClickListener(preference1 -> {
- // TODO(b/258471384): open the buttons destination within wallpaper picker.
final Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);
final String packageName =
mContext.getString(R.string.config_wallpaper_picker_package);
if (!TextUtils.isEmpty(packageName)) {
intent.setPackage(packageName);
}
+ intent.putExtra("destination", "quick_affordances");
mContext.startActivity(intent);
return true;
});
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTip.java
index 2ba3dcd..dae4af4 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTip.java
@@ -90,7 +90,8 @@
@Override
public int getIconId() {
- return R.drawable.ic_battery_status_protected_24dp;
+ return mMode == DockDefenderMode.ACTIVE ? R.drawable.ic_battery_status_protected_24dp :
+ R.drawable.ic_battery_dock_defender_untriggered_24dp;
}
@Override
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
index 90610f8..c2eab57 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
@@ -21,30 +21,22 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.res.Configuration;
-import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
-import android.text.TextUtils;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.View;
-import android.view.accessibility.AccessibilityManager;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
-import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settings.fuelgauge.AdvancedPowerUsageDetail;
-import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -54,73 +46,70 @@
import com.android.settingslib.core.lifecycle.events.OnDestroy;
import com.android.settingslib.core.lifecycle.events.OnResume;
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
-import com.android.settingslib.utils.StringUtil;
-import com.android.settingslib.widget.FooterPreference;
+
+import com.google.common.base.Objects;
import java.util.ArrayList;
import java.util.Calendar;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** Controls the update for chart graph and the list items. */
public class BatteryChartPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnCreate, OnDestroy,
- OnSaveInstanceState, OnResume, ExpandDividerPreference.OnExpandListener {
+ OnSaveInstanceState, OnResume {
private static final String TAG = "BatteryChartPreferenceController";
- private static final String KEY_FOOTER_PREF = "battery_graph_footer";
- private static final String PACKAGE_NAME_NONE = "none";
- private static final int ENABLED_ICON_ALPHA = 255;
- private static final int DISABLED_ICON_ALPHA = 255 / 3;
+ private static final String PREFERENCE_KEY = "battery_chart";
private static final long FADE_IN_ANIMATION_DURATION = 400L;
private static final long FADE_OUT_ANIMATION_DURATION = 200L;
// Keys for bundle instance to restore configurations.
- private static final String KEY_EXPAND_SYSTEM_INFO = "expand_system_info";
private static final String KEY_DAILY_CHART_INDEX = "daily_chart_index";
private static final String KEY_HOURLY_CHART_INDEX = "hourly_chart_index";
private static int sUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
- @VisibleForTesting
- Map<Integer, Map<Integer, BatteryDiffData>> mBatteryUsageMap;
+ /**
+ * A callback listener for battery usage is updated.
+ * This happens when battery usage data is ready or the selected index is changed.
+ */
+ public interface OnBatteryUsageUpdatedListener {
+ /**
+ * The callback function for battery usage is updated.
+ * @param slotUsageData The battery usage diff data for the selected slot. This is used in
+ * the app list.
+ * @param slotTimestamp The selected slot timestamp information. This is used in the battery
+ * usage breakdown category.
+ * @param isAllUsageDataEmpty Whether all the battery usage data is null or empty. This is
+ * used when showing the footer.
+ */
+ void onBatteryUsageUpdated(
+ BatteryDiffData slotUsageData, String slotTimestamp, boolean isAllUsageDataEmpty);
+ }
@VisibleForTesting
Context mPrefContext;
@VisibleForTesting
- BatteryUtils mBatteryUtils;
- @VisibleForTesting
- PreferenceGroup mAppListPrefGroup;
- @VisibleForTesting
- ExpandDividerPreference mExpandDividerPreference;
- @VisibleForTesting
- boolean mIsExpanded = false;
-
- @VisibleForTesting
BatteryChartView mDailyChartView;
@VisibleForTesting
BatteryChartView mHourlyChartView;
-
@VisibleForTesting
int mDailyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
@VisibleForTesting
int mHourlyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
+ @VisibleForTesting
+ Map<Integer, Map<Integer, BatteryDiffData>> mBatteryUsageMap;
private boolean mIs24HourFormat;
- private boolean mIsFooterPrefAdded = false;
private boolean mHourlyChartVisible = true;
private View mBatteryChartViewGroup;
- private View mCategoryTitleView;
- private PreferenceScreen mPreferenceScreen;
- private FooterPreference mFooterPreference;
private TextView mChartSummaryTextView;
private BatteryChartViewModel mDailyViewModel;
private List<BatteryChartViewModel> mHourlyViewModels;
+ private OnBatteryUsageUpdatedListener mOnBatteryUsageUpdatedListener;
- private final String mPreferenceKey;
private final SettingsActivity mActivity;
- private final InstrumentedPreferenceFragment mFragment;
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final AnimatorListenerAdapter mHourlyChartFadeInAdapter =
@@ -135,18 +124,10 @@
final HourlyChartLabelTextGenerator mHourlyChartLabelTextGenerator =
new HourlyChartLabelTextGenerator();
- // Preference cache to avoid create new instance each time.
- @VisibleForTesting
- final Map<String, Preference> mPreferenceCache = new HashMap<>();
-
public BatteryChartPreferenceController(
- Context context, String preferenceKey,
- Lifecycle lifecycle, SettingsActivity activity,
- InstrumentedPreferenceFragment fragment) {
+ Context context, Lifecycle lifecycle, SettingsActivity activity) {
super(context);
mActivity = activity;
- mFragment = fragment;
- mPreferenceKey = preferenceKey;
mIs24HourFormat = DateFormat.is24HourFormat(context);
mMetricsFeatureProvider =
FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
@@ -164,10 +145,8 @@
savedInstanceState.getInt(KEY_DAILY_CHART_INDEX, mDailyChartIndex);
mHourlyChartIndex =
savedInstanceState.getInt(KEY_HOURLY_CHART_INDEX, mHourlyChartIndex);
- mIsExpanded =
- savedInstanceState.getBoolean(KEY_EXPAND_SYSTEM_INFO, mIsExpanded);
- Log.d(TAG, String.format("onCreate() dailyIndex=%d hourlyIndex=%d isExpanded=%b",
- mDailyChartIndex, mHourlyChartIndex, mIsExpanded));
+ Log.d(TAG, String.format("onCreate() dailyIndex=%d hourlyIndex=%d",
+ mDailyChartIndex, mHourlyChartIndex));
}
@Override
@@ -191,9 +170,8 @@
}
savedInstance.putInt(KEY_DAILY_CHART_INDEX, mDailyChartIndex);
savedInstance.putInt(KEY_HOURLY_CHART_INDEX, mHourlyChartIndex);
- savedInstance.putBoolean(KEY_EXPAND_SYSTEM_INFO, mIsExpanded);
- Log.d(TAG, String.format("onSaveInstanceState() dailyIndex=%d hourlyIndex=%d isExpanded=%b",
- mDailyChartIndex, mHourlyChartIndex, mIsExpanded));
+ Log.d(TAG, String.format("onSaveInstanceState() dailyIndex=%d hourlyIndex=%d",
+ mDailyChartIndex, mHourlyChartIndex));
}
@Override
@@ -202,25 +180,12 @@
BatteryDiffEntry.clearCache();
}
mHandler.removeCallbacksAndMessages(/*token=*/ null);
- mPreferenceCache.clear();
- if (mAppListPrefGroup != null) {
- mAppListPrefGroup.removeAll();
- }
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- mPreferenceScreen = screen;
mPrefContext = screen.getContext();
- mAppListPrefGroup = screen.findPreference(mPreferenceKey);
- mAppListPrefGroup.setOrderingAsAdded(false);
- mAppListPrefGroup.setTitle("");
- mFooterPreference = screen.findPreference(KEY_FOOTER_PREF);
- // Removes footer first until usage data is loaded to avoid flashing.
- if (mFooterPreference != null) {
- screen.removePreference(mFooterPreference);
- }
}
@Override
@@ -230,42 +195,11 @@
@Override
public String getPreferenceKey() {
- return mPreferenceKey;
+ return PREFERENCE_KEY;
}
- @Override
- public boolean handlePreferenceTreeClick(Preference preference) {
- if (!(preference instanceof PowerGaugePreference)) {
- return false;
- }
- final PowerGaugePreference powerPref = (PowerGaugePreference) preference;
- final BatteryDiffEntry diffEntry = powerPref.getBatteryDiffEntry();
- final BatteryHistEntry histEntry = diffEntry.mBatteryHistEntry;
- final String packageName = histEntry.mPackageName;
- final boolean isAppEntry = histEntry.isAppEntry();
- mMetricsFeatureProvider.action(
- /* attribution */ SettingsEnums.OPEN_BATTERY_USAGE,
- /* action */ isAppEntry
- ? SettingsEnums.ACTION_BATTERY_USAGE_APP_ITEM
- : SettingsEnums.ACTION_BATTERY_USAGE_SYSTEM_ITEM,
- /* pageId */ SettingsEnums.OPEN_BATTERY_USAGE,
- TextUtils.isEmpty(packageName) ? PACKAGE_NAME_NONE : packageName,
- (int) Math.round(diffEntry.getPercentOfTotal()));
- Log.d(TAG, String.format("handleClick() label=%s key=%s package=%s",
- diffEntry.getAppLabel(), histEntry.getKey(), histEntry.mPackageName));
- AdvancedPowerUsageDetail.startBatteryDetailPage(
- mActivity, mFragment, diffEntry, powerPref.getPercent(), getSlotInformation());
- return true;
- }
-
- @Override
- public void onExpand(boolean isExpanded) {
- mIsExpanded = isExpanded;
- mMetricsFeatureProvider.action(
- mPrefContext,
- SettingsEnums.ACTION_BATTERY_USAGE_EXPAND_ITEM,
- isExpanded);
- refreshExpandUi();
+ void setOnBatteryUsageUpdatedListener(OnBatteryUsageUpdatedListener listener) {
+ mOnBatteryUsageUpdatedListener = listener;
}
void setBatteryHistoryMap(
@@ -306,7 +240,8 @@
hourlyBatteryLevelsPerDay.getLevels(),
hourlyBatteryLevelsPerDay.getTimestamps(),
BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS,
- mHourlyChartLabelTextGenerator));
+ mHourlyChartLabelTextGenerator.setLatestTimestamp(getLast(getLast(
+ batteryLevelData.getHourlyBatteryLevelsPerDay()).getTimestamps()))));
}
refreshUi();
}
@@ -339,7 +274,6 @@
mDailyChartIndex = trapezoidIndex;
mHourlyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
refreshUi();
- requestAccessibilityFocusForCategoryTitle(mDailyChartView);
mMetricsFeatureProvider.action(
mPrefContext,
trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_ALL
@@ -355,7 +289,6 @@
Log.d(TAG, "onHourlyChartSelect:" + trapezoidIndex);
mHourlyChartIndex = trapezoidIndex;
refreshUi();
- requestAccessibilityFocusForCategoryTitle(mHourlyChartView);
mMetricsFeatureProvider.action(
mPrefContext,
trapezoidIndex == BatteryChartViewModel.SELECTED_INDEX_ALL
@@ -385,14 +318,14 @@
return false;
}
- mHandler.post(() -> {
- final long start = System.currentTimeMillis();
- removeAndCacheAllPrefs();
- addAllPreferences();
- refreshCategoryTitle();
- Log.d(TAG, String.format("refreshUi is finished in %d/ms",
- (System.currentTimeMillis() - start)));
- });
+
+ if (mOnBatteryUsageUpdatedListener != null && mBatteryUsageMap != null
+ && mBatteryUsageMap.get(mDailyChartIndex) != null) {
+ final BatteryDiffData slotUsageData =
+ mBatteryUsageMap.get(mDailyChartIndex).get(mHourlyChartIndex);
+ mOnBatteryUsageUpdatedListener.onBatteryUsageUpdated(
+ slotUsageData, getSlotInformation(), isBatteryUsageMapNullOrEmpty());
+ }
return true;
}
@@ -414,9 +347,6 @@
mDailyChartView.setVisibility(View.GONE);
mHourlyChartView.setVisibility(View.VISIBLE);
mHourlyChartView.setViewModel(null);
- removeAndCacheAllPrefs();
- addFooterPreferenceIfNeeded(false);
- return false;
}
return true;
}
@@ -430,6 +360,9 @@
mDailyChartIndex = 0;
} else {
mDailyChartView.setVisibility(View.VISIBLE);
+ if (mDailyChartIndex >= mDailyViewModel.size()) {
+ mDailyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
+ }
mDailyViewModel.setSelectedIndex(mDailyChartIndex);
mDailyChartView.setViewModel(mDailyViewModel);
}
@@ -441,6 +374,9 @@
animateBatteryHourlyChartView(/*visible=*/ true);
final BatteryChartViewModel hourlyViewModel =
mHourlyViewModels.get(mDailyChartIndex);
+ if (mHourlyChartIndex >= hourlyViewModel.size()) {
+ mHourlyChartIndex = BatteryChartViewModel.SELECTED_INDEX_ALL;
+ }
hourlyViewModel.setSelectedIndex(mHourlyChartIndex);
mHourlyChartView.setViewModel(hourlyViewModel);
}
@@ -452,154 +388,6 @@
return true;
}
- private void addAllPreferences() {
- final BatteryDiffData batteryDiffData =
- mBatteryUsageMap.get(mDailyChartIndex).get(mHourlyChartIndex);
- addFooterPreferenceIfNeeded(batteryDiffData != null
- && (!batteryDiffData.getAppDiffEntryList().isEmpty()
- || !batteryDiffData.getSystemDiffEntryList().isEmpty()));
- if (batteryDiffData == null) {
- Log.w(TAG, "cannot find BatteryDiffEntry for daily_index: " + mDailyChartIndex
- + " hourly_index: " + mHourlyChartIndex);
- return;
- }
- // Adds app entries to the list if it is not empty.
- if (!batteryDiffData.getAppDiffEntryList().isEmpty()) {
- addPreferenceToScreen(batteryDiffData.getAppDiffEntryList());
- }
- // Adds the expandable divider if we have system entries data.
- if (!batteryDiffData.getSystemDiffEntryList().isEmpty()) {
- if (mExpandDividerPreference == null) {
- mExpandDividerPreference = new ExpandDividerPreference(mPrefContext);
- mExpandDividerPreference.setOnExpandListener(this);
- mExpandDividerPreference.setIsExpanded(mIsExpanded);
- }
- mExpandDividerPreference.setOrder(
- mAppListPrefGroup.getPreferenceCount());
- mAppListPrefGroup.addPreference(mExpandDividerPreference);
- }
- refreshExpandUi();
- }
-
- @VisibleForTesting
- void addPreferenceToScreen(List<BatteryDiffEntry> entries) {
- if (mAppListPrefGroup == null || entries.isEmpty()) {
- return;
- }
- int prefIndex = mAppListPrefGroup.getPreferenceCount();
- for (BatteryDiffEntry entry : entries) {
- boolean isAdded = false;
- final String appLabel = entry.getAppLabel();
- final Drawable appIcon = entry.getAppIcon();
- if (TextUtils.isEmpty(appLabel) || appIcon == null) {
- Log.w(TAG, "cannot find app resource for:" + entry.getPackageName());
- continue;
- }
- final String prefKey = entry.mBatteryHistEntry.getKey();
- PowerGaugePreference pref = mAppListPrefGroup.findPreference(prefKey);
- if (pref != null) {
- isAdded = true;
- Log.w(TAG, "preference should be removed for:" + entry.getPackageName());
- } else {
- pref = (PowerGaugePreference) mPreferenceCache.get(prefKey);
- }
- // Creates new innstance if cached preference is not found.
- if (pref == null) {
- pref = new PowerGaugePreference(mPrefContext);
- pref.setKey(prefKey);
- mPreferenceCache.put(prefKey, pref);
- }
- pref.setIcon(appIcon);
- pref.setTitle(appLabel);
- pref.setOrder(prefIndex);
- pref.setPercent(entry.getPercentOfTotal());
- pref.setSingleLineTitle(true);
- // Sets the BatteryDiffEntry to preference for launching detailed page.
- pref.setBatteryDiffEntry(entry);
- pref.setEnabled(entry.validForRestriction());
- setPreferenceSummary(pref, entry);
- if (!isAdded) {
- mAppListPrefGroup.addPreference(pref);
- }
- appIcon.setAlpha(pref.isEnabled() ? ENABLED_ICON_ALPHA : DISABLED_ICON_ALPHA);
- prefIndex++;
- }
- }
-
- private void removeAndCacheAllPrefs() {
- if (mAppListPrefGroup == null
- || mAppListPrefGroup.getPreferenceCount() == 0) {
- return;
- }
- final int prefsCount = mAppListPrefGroup.getPreferenceCount();
- for (int index = 0; index < prefsCount; index++) {
- final Preference pref = mAppListPrefGroup.getPreference(index);
- if (TextUtils.isEmpty(pref.getKey())) {
- continue;
- }
- mPreferenceCache.put(pref.getKey(), pref);
- }
- mAppListPrefGroup.removeAll();
- }
-
- private void refreshExpandUi() {
- final List<BatteryDiffEntry> systemEntries = mBatteryUsageMap.get(mDailyChartIndex).get(
- mHourlyChartIndex).getSystemDiffEntryList();
- if (mIsExpanded) {
- addPreferenceToScreen(systemEntries);
- } else {
- // Removes and recycles all system entries to hide all of them.
- for (BatteryDiffEntry entry : systemEntries) {
- final String prefKey = entry.mBatteryHistEntry.getKey();
- final Preference pref = mAppListPrefGroup.findPreference(prefKey);
- if (pref != null) {
- mAppListPrefGroup.removePreference(pref);
- mPreferenceCache.put(pref.getKey(), pref);
- }
- }
- }
- }
-
- @VisibleForTesting
- void refreshCategoryTitle() {
- final String slotInformation = getSlotInformation();
- Log.d(TAG, String.format("refreshCategoryTitle:%s", slotInformation));
- if (mAppListPrefGroup != null) {
- mAppListPrefGroup.setTitle(
- getSlotInformation(/*isApp=*/ true, slotInformation));
- }
- if (mExpandDividerPreference != null) {
- mExpandDividerPreference.setTitle(
- getSlotInformation(/*isApp=*/ false, slotInformation));
- }
- }
-
- private void requestAccessibilityFocusForCategoryTitle(View view) {
- if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
- return;
- }
- if (mCategoryTitleView == null) {
- mCategoryTitleView = view.getRootView().findViewById(com.android.internal.R.id.title);
- }
- if (mCategoryTitleView != null) {
- mCategoryTitleView.requestAccessibilityFocus();
- }
- }
-
- private String getSlotInformation(boolean isApp, String slotInformation) {
- // TODO: Updates the right slot information from daily and hourly chart selection.
- // Null means we show all information without a specific time slot.
- if (slotInformation == null) {
- return isApp
- ? mPrefContext.getString(R.string.battery_app_usage)
- : mPrefContext.getString(R.string.battery_system_usage);
- } else {
- return isApp
- ? mPrefContext.getString(R.string.battery_app_usage_for, slotInformation)
- : mPrefContext.getString(R.string.battery_system_usage_for, slotInformation);
- }
- }
-
@VisibleForTesting
String getSlotInformation() {
if (mDailyViewModel == null || mHourlyViewModels == null) {
@@ -624,51 +412,6 @@
return String.format("%s %s", selectedDayText, selectedHourText);
}
- @VisibleForTesting
- void setPreferenceSummary(
- PowerGaugePreference preference, BatteryDiffEntry entry) {
- final long foregroundUsageTimeInMs = entry.mForegroundUsageTimeInMs;
- final long backgroundUsageTimeInMs = entry.mBackgroundUsageTimeInMs;
- // TODO: update this value after the new API for foreground service is completed.
- final long totalUsageTimeInMs = foregroundUsageTimeInMs + backgroundUsageTimeInMs;
- String usageTimeSummary = null;
- // Not shows summary for some system components without usage time.
- if (totalUsageTimeInMs == 0) {
- preference.setSummary(null);
- // Shows background summary only if we don't have foreground usage time.
- } else if (foregroundUsageTimeInMs == 0 && backgroundUsageTimeInMs != 0) {
- usageTimeSummary = buildUsageTimeInfo(backgroundUsageTimeInMs, true);
- // Shows total usage summary only if total usage time is small.
- } else if (totalUsageTimeInMs < DateUtils.MINUTE_IN_MILLIS) {
- usageTimeSummary = buildUsageTimeInfo(totalUsageTimeInMs, false);
- } else {
- usageTimeSummary = buildUsageTimeInfo(totalUsageTimeInMs, false);
- // Shows background usage time if it is larger than a minute.
- if (backgroundUsageTimeInMs > 0) {
- usageTimeSummary +=
- "\n" + buildUsageTimeInfo(backgroundUsageTimeInMs, true);
- }
- }
- preference.setSummary(usageTimeSummary);
- }
-
- private String buildUsageTimeInfo(long usageTimeInMs, boolean isBackground) {
- if (usageTimeInMs < DateUtils.MINUTE_IN_MILLIS) {
- return mPrefContext.getString(
- isBackground
- ? R.string.battery_usage_background_less_than_one_minute
- : R.string.battery_usage_total_less_than_one_minute);
- }
- final CharSequence timeSequence =
- StringUtil.formatElapsedTime(mPrefContext, usageTimeInMs,
- /*withSeconds=*/ false, /*collapseTimeUnit=*/ false);
- final int resourceId =
- isBackground
- ? R.string.battery_usage_for_background_time
- : R.string.battery_usage_for_total_time;
- return mPrefContext.getString(resourceId, timeSequence);
- }
-
private void animateBatteryChartViewGroup() {
if (mBatteryChartViewGroup != null && mBatteryChartViewGroup.getAlpha() == 0) {
mBatteryChartViewGroup.animate().alpha(1f).setDuration(FADE_IN_ANIMATION_DURATION)
@@ -726,18 +469,6 @@
};
}
- private void addFooterPreferenceIfNeeded(boolean containAppItems) {
- if (mIsFooterPrefAdded || mFooterPreference == null) {
- return;
- }
- mIsFooterPrefAdded = true;
- mFooterPreference.setTitle(mPrefContext.getString(
- containAppItems
- ? R.string.battery_usage_screen_footer
- : R.string.battery_usage_screen_footer_empty));
- mHandler.post(() -> mPreferenceScreen.addPreference(mFooterPreference));
- }
-
private boolean isBatteryLevelDataInOneDay() {
return mHourlyViewModels != null && mHourlyViewModels.size() == 1;
}
@@ -748,6 +479,19 @@
&& mHourlyChartIndex == BatteryChartViewModel.SELECTED_INDEX_ALL;
}
+ private boolean isBatteryUsageMapNullOrEmpty() {
+ if (mBatteryUsageMap == null) {
+ return true;
+ }
+ BatteryDiffData allBatteryDiffData = mBatteryUsageMap
+ .get(BatteryChartViewModel.SELECTED_INDEX_ALL)
+ .get(BatteryChartViewModel.SELECTED_INDEX_ALL);
+ // If all data is null or empty, each slot must be null or empty.
+ return allBatteryDiffData == null
+ || (allBatteryDiffData.getAppDiffEntryList().isEmpty()
+ && allBatteryDiffData.getSystemDiffEntryList().isEmpty());
+ }
+
@VisibleForTesting
static int getTotalHours(final BatteryLevelData batteryLevelData) {
if (batteryLevelData == null) {
@@ -780,6 +524,13 @@
return allBatteryDiffData == null ? null : allBatteryDiffData.getAppDiffEntryList();
}
+ private static <T> T getLast(List<T> list) {
+ if (list == null || list.isEmpty()) {
+ return null;
+ }
+ return list.get(list.size() - 1);
+ }
+
/** Used for {@link AppBatteryPreferenceController}. */
public static BatteryDiffEntry getAppBatteryUsageData(
Context context, String packageName, int userId) {
@@ -819,18 +570,33 @@
private final class HourlyChartLabelTextGenerator implements
BatteryChartViewModel.LabelTextGenerator {
+ private Long mLatestTimestamp;
+
@Override
public String generateText(List<Long> timestamps, int index) {
+ if (Objects.equal(timestamps.get(index), mLatestTimestamp)) {
+ // Replaces the latest timestamp text to "now".
+ return mContext.getString(R.string.battery_usage_chart_label_now);
+ }
return ConvertUtils.utcToLocalTimeHour(mContext, timestamps.get(index),
mIs24HourFormat);
}
@Override
public String generateFullText(List<Long> timestamps, int index) {
+ if (Objects.equal(timestamps.get(index), mLatestTimestamp)) {
+ // Replaces the latest timestamp text to "now".
+ return mContext.getString(R.string.battery_usage_chart_label_now);
+ }
return index == timestamps.size() - 1
? generateText(timestamps, index)
: String.format("%s%s%s", generateText(timestamps, index),
- mIs24HourFormat ? "-" : " - ", generateText(timestamps, index + 1));
+ mIs24HourFormat ? "-" : " - ", generateText(timestamps, index + 1));
+ }
+
+ public HourlyChartLabelTextGenerator setLatestTimestamp(Long latestTimestamp) {
+ this.mLatestTimestamp = latestTimestamp;
+ return this;
}
}
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java
index b5d4dde..caf2cf3 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffData.java
@@ -26,23 +26,14 @@
private final List<BatteryDiffEntry> mAppEntries;
private final List<BatteryDiffEntry> mSystemEntries;
- /** Constructor for the diff entries which already have totalConsumePower value. */
+ /** Constructor for the diff entries. */
public BatteryDiffData(
@NonNull List<BatteryDiffEntry> appDiffEntries,
@NonNull List<BatteryDiffEntry> systemDiffEntries) {
mAppEntries = appDiffEntries;
mSystemEntries = systemDiffEntries;
- sortEntries();
- }
-
- /** Constructor for the diff entries which have not set totalConsumePower value. */
- public BatteryDiffData(
- @NonNull List<BatteryDiffEntry> appDiffEntries,
- @NonNull List<BatteryDiffEntry> systemDiffEntries,
- final double totalConsumePower) {
- mAppEntries = appDiffEntries;
- mSystemEntries = systemDiffEntries;
- setTotalConsumePowerForAllEntries(totalConsumePower);
+ setTotalConsumePowerForAllEntries(mAppEntries);
+ setTotalConsumePowerForAllEntries(mSystemEntries);
sortEntries();
}
@@ -55,9 +46,14 @@
}
// Sets total consume power for each entry.
- private void setTotalConsumePowerForAllEntries(final double totalConsumePower) {
- mAppEntries.forEach(diffEntry -> diffEntry.setTotalConsumePower(totalConsumePower));
- mSystemEntries.forEach(diffEntry -> diffEntry.setTotalConsumePower(totalConsumePower));
+ private void setTotalConsumePowerForAllEntries(List<BatteryDiffEntry> batteryDiffEntries) {
+ double totalConsumePower = 0.0;
+ for (BatteryDiffEntry batteryDiffEntry : batteryDiffEntries) {
+ totalConsumePower += batteryDiffEntry.mConsumePower;
+ }
+ for (BatteryDiffEntry batteryDiffEntry : batteryDiffEntries) {
+ batteryDiffEntry.setTotalConsumePower(totalConsumePower);
+ }
}
// Sorts entries based on consumed percentage.
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java
index 32711bf..496200e 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntry.java
@@ -52,7 +52,6 @@
(a, b) -> Double.compare(b.getPercentOfTotal(), a.getPercentOfTotal());
public long mForegroundUsageTimeInMs;
- public long mForegroundServiceUsageTimeInMs;
public long mBackgroundUsageTimeInMs;
public double mConsumePower;
public double mForegroundUsageConsumePower;
@@ -83,7 +82,6 @@
public BatteryDiffEntry(
Context context,
long foregroundUsageTimeInMs,
- long foregroundServiceUsageTimeInMs,
long backgroundUsageTimeInMs,
double consumePower,
double foregroundUsageConsumePower,
@@ -98,7 +96,6 @@
mBackgroundUsageConsumePower = backgroundUsageConsumePower;
mCachedUsageConsumePower = cachedUsageConsumePower;
mForegroundUsageTimeInMs = foregroundUsageTimeInMs;
- mForegroundServiceUsageTimeInMs = foregroundServiceUsageTimeInMs;
mBackgroundUsageTimeInMs = backgroundUsageTimeInMs;
mBatteryHistEntry = batteryHistEntry;
mUserManager = context.getSystemService(UserManager.class);
@@ -121,7 +118,6 @@
return new BatteryDiffEntry(
this.mContext,
this.mForegroundUsageTimeInMs,
- this.mForegroundServiceUsageTimeInMs,
this.mBackgroundUsageTimeInMs,
this.mConsumePower,
this.mForegroundUsageConsumePower,
@@ -385,14 +381,9 @@
mForegroundUsageConsumePower, mForegroundServiceUsageConsumePower))
.append(String.format("\n\tconsume power= background:%f cached:%f",
mBackgroundUsageConsumePower, mCachedUsageConsumePower))
- .append(String.format("\n\ttime= foreground:%s foregroundService:%s background:%s",
+ .append(String.format("\n\ttime= foreground:%s background:%s",
StringUtil.formatElapsedTime(mContext, (double) mForegroundUsageTimeInMs,
/*withSeconds=*/ true, /*collapseTimeUnit=*/ false),
- StringUtil.formatElapsedTime(
- mContext,
- (double) mForegroundServiceUsageTimeInMs,
- /*withSeconds=*/ true,
- /*collapseTimeUnit=*/ false),
StringUtil.formatElapsedTime(mContext, (double) mBackgroundUsageTimeInMs,
/*withSeconds=*/ true, /*collapseTimeUnit=*/ false)))
.append(String.format("\n\tpackage:%s|%s uid:%d userId:%d",
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
index 36a9248..e9e0347 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java
@@ -112,7 +112,6 @@
private final int mPowerComponentId;
private long mUsageDurationMs;
private long mTimeInForegroundMs;
- private long mTimeInForegroundServiceMs;
private long mTimeInBackgroundMs;
public String mName;
@@ -176,9 +175,6 @@
getQuickNameIconForUid(uid, packages, loadDataInBackground);
mTimeInForegroundMs =
uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND);
- //TODO: update this to the correct API after the new API is completed.
- mTimeInForegroundServiceMs =
- uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND);
mTimeInBackgroundMs =
uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND);
mConsumedPowerInForeground = safeGetConsumedPower(
@@ -204,16 +200,13 @@
/** Battery entry for a power component of AggregateBatteryConsumer */
public BatteryEntry(Context context, int powerComponentId, double devicePowerMah,
- double appsPowerMah, long usageDurationMs) {
+ long usageDurationMs) {
mContext = context;
mBatteryConsumer = null;
mUid = Process.INVALID_UID;
mIsHidden = false;
mPowerComponentId = powerComponentId;
- mConsumedPower =
- powerComponentId == BatteryConsumer.POWER_COMPONENT_SCREEN
- ? devicePowerMah
- : devicePowerMah - appsPowerMah;
+ mConsumedPower = devicePowerMah;
mUsageDurationMs = usageDurationMs;
mConsumerType = ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY;
@@ -228,7 +221,7 @@
/** Battery entry for a custom power component of AggregateBatteryConsumer */
public BatteryEntry(Context context, int powerComponentId, String powerComponentName,
- double devicePowerMah, double appsPowerMah) {
+ double devicePowerMah) {
mContext = context;
mBatteryConsumer = null;
mUid = Process.INVALID_UID;
@@ -238,10 +231,7 @@
mIconId = R.drawable.ic_power_system;
mIcon = context.getDrawable(mIconId);
mName = powerComponentName;
- mConsumedPower =
- powerComponentId == BatteryConsumer.POWER_COMPONENT_SCREEN
- ? devicePowerMah
- : devicePowerMah - appsPowerMah;
+ mConsumedPower = devicePowerMah;
mConsumerType = ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY;
}
@@ -436,15 +426,6 @@
}
}
- /** Returns foreground service time/ms that is attributed to this entry. */
- public long getTimeInForegroundServiceMs() {
- if (mBatteryConsumer instanceof UidBatteryConsumer) {
- return mTimeInForegroundServiceMs;
- } else {
- return 0;
- }
- }
-
/** Returns background activity time/ms that is attributed to this entry. */
public long getTimeInBackgroundMs() {
if (mBatteryConsumer instanceof UidBatteryConsumer) {
@@ -518,9 +499,6 @@
UidBatteryConsumer uidBatteryConsumer = (UidBatteryConsumer) batteryConsumer;
mTimeInForegroundMs += uidBatteryConsumer.getTimeInStateMs(
UidBatteryConsumer.STATE_FOREGROUND);
- //TODO: update this to the correct API after the new API is completed.
- mTimeInForegroundServiceMs += uidBatteryConsumer.getTimeInStateMs(
- UidBatteryConsumer.STATE_FOREGROUND);
mTimeInBackgroundMs += uidBatteryConsumer.getTimeInStateMs(
UidBatteryConsumer.STATE_BACKGROUND);
mConsumedPowerInForeground += safeGetConsumedPower(
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntry.java
index 5cd63e8..2cfb526 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntry.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntry.java
@@ -56,7 +56,6 @@
public final double mCachedUsageConsumePower;
public final double mPercentOfTotal;
public final long mForegroundUsageTimeInMs;
- public final long mForegroundServiceUsageTimeInMs;
public final long mBackgroundUsageTimeInMs;
@BatteryConsumer.PowerComponent
public final int mDrainType;
@@ -91,7 +90,6 @@
mCachedUsageConsumePower = batteryInformation.getCachedUsageConsumePower();
mPercentOfTotal = batteryInformation.getPercentOfTotal();
mForegroundUsageTimeInMs = batteryInformation.getForegroundUsageTimeInMs();
- mForegroundServiceUsageTimeInMs = batteryInformation.getForegroundServiceUsageTimeInMs();
mBackgroundUsageTimeInMs = batteryInformation.getBackgroundUsageTimeInMs();
mDrainType = batteryInformation.getDrainType();
final DeviceBatteryState deviceBatteryState = batteryInformation.getDeviceBatteryState();
@@ -121,7 +119,6 @@
mCachedUsageConsumePower = batteryInformation.getCachedUsageConsumePower();
mPercentOfTotal = batteryInformation.getPercentOfTotal();
mForegroundUsageTimeInMs = batteryInformation.getForegroundUsageTimeInMs();
- mForegroundServiceUsageTimeInMs = batteryInformation.getForegroundServiceUsageTimeInMs();
mBackgroundUsageTimeInMs = batteryInformation.getBackgroundUsageTimeInMs();
mDrainType = batteryInformation.getDrainType();
final DeviceBatteryState deviceBatteryState = batteryInformation.getDeviceBatteryState();
@@ -141,7 +138,6 @@
double backgroundUsageConsumePower,
double cachedUsageConsumePower,
long foregroundUsageTimeInMs,
- long foregroundServiceUsageTimeInMs,
long backgroundUsageTimeInMs,
int batteryLevel) {
mUid = fromEntry.mUid;
@@ -160,7 +156,6 @@
mCachedUsageConsumePower = cachedUsageConsumePower;
mPercentOfTotal = fromEntry.mPercentOfTotal;
mForegroundUsageTimeInMs = foregroundUsageTimeInMs;
- mForegroundServiceUsageTimeInMs = foregroundServiceUsageTimeInMs;
mBackgroundUsageTimeInMs = backgroundUsageTimeInMs;
mDrainType = fromEntry.mDrainType;
mConsumerType = fromEntry.mConsumerType;
@@ -223,9 +218,8 @@
mForegroundUsageConsumePower, mForegroundServiceUsageConsumePower))
.append(String.format("\n\tbackground=%f|cached=%f",
mBackgroundUsageConsumePower, mCachedUsageConsumePower))
- .append(String.format("\n\telapsedTime=%d|%d|%d",
+ .append(String.format("\n\telapsedTime=%d|%d",
Duration.ofMillis(mForegroundUsageTimeInMs).getSeconds(),
- Duration.ofMillis(mForegroundServiceUsageTimeInMs).getSeconds(),
Duration.ofMillis(mBackgroundUsageTimeInMs).getSeconds()))
.append(String.format("\n\tdrainType=%d|consumerType=%d",
mDrainType, mConsumerType))
@@ -320,12 +314,6 @@
(double) (lowerHistEntry == null ? 0 : lowerHistEntry.mForegroundUsageTimeInMs),
(double) upperHistEntry.mForegroundUsageTimeInMs,
ratio);
- final double foregroundServiceUsageTimeInMs = interpolate(
- (double) (lowerHistEntry == null
- ? 0
- : lowerHistEntry.mForegroundServiceUsageTimeInMs),
- (double) upperHistEntry.mForegroundServiceUsageTimeInMs,
- ratio);
final double backgroundUsageTimeInMs = interpolate(
(double) (lowerHistEntry == null ? 0 : lowerHistEntry.mBackgroundUsageTimeInMs),
(double) upperHistEntry.mBackgroundUsageTimeInMs,
@@ -338,7 +326,6 @@
|| upperHistEntry.mBackgroundUsageConsumePower < backgroundUsageConsumePower
|| upperHistEntry.mCachedUsageConsumePower < cachedUsageConsumePower
|| upperHistEntry.mForegroundUsageTimeInMs < foregroundUsageTimeInMs
- || upperHistEntry.mForegroundServiceUsageTimeInMs < foregroundServiceUsageTimeInMs
|| upperHistEntry.mBackgroundUsageTimeInMs < backgroundUsageTimeInMs) {
if (DEBUG) {
Log.w(TAG, String.format(
@@ -365,7 +352,6 @@
backgroundUsageConsumePower,
cachedUsageConsumePower,
Math.round(foregroundUsageTimeInMs),
- Math.round(foregroundServiceUsageTimeInMs),
Math.round(backgroundUsageTimeInMs),
(int) Math.round(batteryLevel));
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java
new file mode 100644
index 0000000..1452b54
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge.batteryusage;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Looper;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.util.Log;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceGroup;
+import androidx.preference.PreferenceScreen;
+import androidx.viewpager2.widget.ViewPager2;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settings.fuelgauge.AdvancedPowerUsageDetail;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnDestroy;
+import com.android.settingslib.utils.StringUtil;
+import com.android.settingslib.widget.FooterPreference;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** Controller for battery usage breakdown preference group. */
+public class BatteryUsageBreakdownController extends BasePreferenceController
+ implements LifecycleObserver, OnDestroy {
+ private static final String TAG = "BatteryUsageBreakdownController";
+ private static final String ROOT_PREFERENCE_KEY = "battery_usage_breakdown";
+ private static final String FOOTER_PREFERENCE_KEY = "battery_usage_footer";
+ private static final String TAB_PREFERENCE_KEY = "battery_usage_tab";
+ private static final String APP_LIST_PREFERENCE_KEY = "app_list";
+ private static final String PACKAGE_NAME_NONE = "none";
+ private static final int ENABLED_ICON_ALPHA = 255;
+ private static final int DISABLED_ICON_ALPHA = 255 / 3;
+
+ private final SettingsActivity mActivity;
+ private final InstrumentedPreferenceFragment mFragment;
+ private final MetricsFeatureProvider mMetricsFeatureProvider;
+ private final Handler mHandler = new Handler(Looper.getMainLooper());
+
+ @VisibleForTesting
+ final Map<String, Preference> mPreferenceCache = new HashMap<>();
+
+ private int mTabPosition;
+ private String mSlotTimestamp;
+
+ @VisibleForTesting
+ Context mPrefContext;
+ @VisibleForTesting
+ PreferenceCategory mRootPreference;
+ @VisibleForTesting
+ TabPreference mTabPreference;
+ @VisibleForTesting
+ PreferenceGroup mAppListPreferenceGroup;
+ @VisibleForTesting
+ FooterPreference mFooterPreference;
+ @VisibleForTesting
+ BatteryDiffData mBatteryDiffData;
+
+ public BatteryUsageBreakdownController(
+ Context context, Lifecycle lifecycle, SettingsActivity activity,
+ InstrumentedPreferenceFragment fragment) {
+ super(context, ROOT_PREFERENCE_KEY);
+ mActivity = activity;
+ mFragment = fragment;
+ mMetricsFeatureProvider =
+ FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ mHandler.removeCallbacksAndMessages(/*token=*/ null);
+ mPreferenceCache.clear();
+ mAppListPreferenceGroup.removeAll();
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public boolean isSliceable() {
+ return false;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!(preference instanceof PowerGaugePreference)) {
+ return false;
+ }
+ final PowerGaugePreference powerPref = (PowerGaugePreference) preference;
+ final BatteryDiffEntry diffEntry = powerPref.getBatteryDiffEntry();
+ final BatteryHistEntry histEntry = diffEntry.mBatteryHistEntry;
+ final String packageName = histEntry.mPackageName;
+ final boolean isAppEntry = histEntry.isAppEntry();
+ mMetricsFeatureProvider.action(
+ /* attribution */ SettingsEnums.OPEN_BATTERY_USAGE,
+ /* action */ isAppEntry
+ ? SettingsEnums.ACTION_BATTERY_USAGE_APP_ITEM
+ : SettingsEnums.ACTION_BATTERY_USAGE_SYSTEM_ITEM,
+ /* pageId */ SettingsEnums.OPEN_BATTERY_USAGE,
+ TextUtils.isEmpty(packageName) ? PACKAGE_NAME_NONE : packageName,
+ (int) Math.round(diffEntry.getPercentOfTotal()));
+ Log.d(TAG, String.format("handleClick() label=%s key=%s package=%s",
+ diffEntry.getAppLabel(), histEntry.getKey(), histEntry.mPackageName));
+ AdvancedPowerUsageDetail.startBatteryDetailPage(
+ mActivity, mFragment, diffEntry, powerPref.getPercent(), mSlotTimestamp);
+ return true;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPrefContext = screen.getContext();
+ mRootPreference = screen.findPreference(ROOT_PREFERENCE_KEY);
+ mTabPreference = screen.findPreference(TAB_PREFERENCE_KEY);
+ mAppListPreferenceGroup = screen.findPreference(APP_LIST_PREFERENCE_KEY);
+ mFooterPreference = screen.findPreference(FOOTER_PREFERENCE_KEY);
+
+ mAppListPreferenceGroup.setOrderingAsAdded(false);
+ mTabPreference.initializeTabs(mFragment, new String[]{
+ mPrefContext.getString(R.string.battery_usage_app_tab),
+ mPrefContext.getString(R.string.battery_usage_system_tab)
+ });
+ mTabPreference.setOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
+ @Override
+ public void onPageSelected(int position) {
+ super.onPageSelected(position);
+ mTabPosition = position;
+ mHandler.post(() -> {
+ removeAndCacheAllPreferences();
+ addAllPreferences();
+ });
+ }
+ });
+ }
+
+ /**
+ * Updates UI when the battery usage is updated.
+ * @param slotUsageData The battery usage diff data for the selected slot. This is used in
+ * the app list.
+ * @param slotTimestamp The selected slot timestamp information. This is used in the battery
+ * usage breakdown category.
+ * @param isAllUsageDataEmpty Whether all the battery usage data is null or empty. This is
+ * used when showing the footer.
+ */
+ void handleBatteryUsageUpdated(
+ BatteryDiffData slotUsageData, String slotTimestamp, boolean isAllUsageDataEmpty) {
+ mBatteryDiffData = slotUsageData;
+ mSlotTimestamp = slotTimestamp;
+
+ showCategoryTitle(slotTimestamp);
+ showTabAndAppList();
+ showFooterPreference(isAllUsageDataEmpty);
+ }
+
+ // TODO: request accessibility focus on category title when slot selection updated.
+ private void showCategoryTitle(String slotTimestamp) {
+ mRootPreference.setTitle(slotTimestamp == null
+ ? mPrefContext.getString(
+ R.string.battery_usage_breakdown_title_since_last_full_charge)
+ : mPrefContext.getString(
+ R.string.battery_usage_breakdown_title_for_slot, slotTimestamp));
+ mRootPreference.setVisible(true);
+ }
+
+ private void showFooterPreference(boolean isAllBatteryUsageEmpty) {
+ mFooterPreference.setTitle(mPrefContext.getString(
+ isAllBatteryUsageEmpty
+ ? R.string.battery_usage_screen_footer_empty
+ : R.string.battery_usage_screen_footer));
+ mFooterPreference.setVisible(true);
+ }
+
+ private void showTabAndAppList() {
+ removeAndCacheAllPreferences();
+ if (mBatteryDiffData == null) {
+ return;
+ }
+ mTabPreference.setVisible(true);
+ mAppListPreferenceGroup.setVisible(true);
+ mHandler.post(() -> {
+ addAllPreferences();
+ });
+ }
+
+ @VisibleForTesting
+ void addAllPreferences() {
+ if (mBatteryDiffData == null) {
+ return;
+ }
+ final long start = System.currentTimeMillis();
+ final List<BatteryDiffEntry> entries = mTabPosition == 0
+ ? mBatteryDiffData.getAppDiffEntryList()
+ : mBatteryDiffData.getSystemDiffEntryList();
+ int prefIndex = mAppListPreferenceGroup.getPreferenceCount();
+ for (BatteryDiffEntry entry : entries) {
+ boolean isAdded = false;
+ final String appLabel = entry.getAppLabel();
+ final Drawable appIcon = entry.getAppIcon();
+ if (TextUtils.isEmpty(appLabel) || appIcon == null) {
+ Log.w(TAG, "cannot find app resource for:" + entry.getPackageName());
+ continue;
+ }
+ final String prefKey = entry.mBatteryHistEntry.getKey();
+ PowerGaugePreference pref = mAppListPreferenceGroup.findPreference(prefKey);
+ if (pref != null) {
+ isAdded = true;
+ Log.w(TAG, "preference should be removed for:" + entry.getPackageName());
+ } else {
+ pref = (PowerGaugePreference) mPreferenceCache.get(prefKey);
+ }
+ // Creates new innstance if cached preference is not found.
+ if (pref == null) {
+ pref = new PowerGaugePreference(mPrefContext);
+ pref.setKey(prefKey);
+ mPreferenceCache.put(prefKey, pref);
+ }
+ pref.setIcon(appIcon);
+ pref.setTitle(appLabel);
+ pref.setOrder(prefIndex);
+ pref.setPercent(entry.getPercentOfTotal());
+ pref.setSingleLineTitle(true);
+ // Sets the BatteryDiffEntry to preference for launching detailed page.
+ pref.setBatteryDiffEntry(entry);
+ pref.setEnabled(entry.validForRestriction());
+ setPreferenceSummary(pref, entry);
+ if (!isAdded) {
+ mAppListPreferenceGroup.addPreference(pref);
+ }
+ appIcon.setAlpha(pref.isEnabled() ? ENABLED_ICON_ALPHA : DISABLED_ICON_ALPHA);
+ prefIndex++;
+ }
+ Log.d(TAG, String.format("addAllPreferences() is finished in %d/ms",
+ (System.currentTimeMillis() - start)));
+ }
+
+ @VisibleForTesting
+ void removeAndCacheAllPreferences() {
+ final int prefsCount = mAppListPreferenceGroup.getPreferenceCount();
+ for (int index = 0; index < prefsCount; index++) {
+ final Preference pref = mAppListPreferenceGroup.getPreference(index);
+ if (TextUtils.isEmpty(pref.getKey())) {
+ continue;
+ }
+ mPreferenceCache.put(pref.getKey(), pref);
+ }
+ mAppListPreferenceGroup.removeAll();
+ }
+
+ @VisibleForTesting
+ void setPreferenceSummary(
+ PowerGaugePreference preference, BatteryDiffEntry entry) {
+ final long foregroundUsageTimeInMs = entry.mForegroundUsageTimeInMs;
+ final long backgroundUsageTimeInMs = entry.mBackgroundUsageTimeInMs;
+ final long totalUsageTimeInMs = foregroundUsageTimeInMs + backgroundUsageTimeInMs;
+ String usageTimeSummary = null;
+ // Not shows summary for some system components without usage time.
+ if (totalUsageTimeInMs == 0) {
+ preference.setSummary(null);
+ // Shows background summary only if we don't have foreground usage time.
+ } else if (foregroundUsageTimeInMs == 0 && backgroundUsageTimeInMs != 0) {
+ usageTimeSummary = buildUsageTimeInfo(backgroundUsageTimeInMs, true);
+ // Shows total usage summary only if total usage time is small.
+ } else if (totalUsageTimeInMs < DateUtils.MINUTE_IN_MILLIS) {
+ usageTimeSummary = buildUsageTimeInfo(totalUsageTimeInMs, false);
+ } else {
+ usageTimeSummary = buildUsageTimeInfo(totalUsageTimeInMs, false);
+ // Shows background usage time if it is larger than a minute.
+ if (backgroundUsageTimeInMs > 0) {
+ usageTimeSummary +=
+ "\n" + buildUsageTimeInfo(backgroundUsageTimeInMs, true);
+ }
+ }
+ preference.setSummary(usageTimeSummary);
+ }
+
+ private String buildUsageTimeInfo(long usageTimeInMs, boolean isBackground) {
+ if (usageTimeInMs < DateUtils.MINUTE_IN_MILLIS) {
+ return mPrefContext.getString(
+ isBackground
+ ? R.string.battery_usage_background_less_than_one_minute
+ : R.string.battery_usage_total_less_than_one_minute);
+ }
+ final CharSequence timeSequence =
+ StringUtil.formatElapsedTime(mPrefContext, (double) usageTimeInMs,
+ /*withSeconds=*/ false, /*collapseTimeUnit=*/ false);
+ final int resourceId =
+ isBackground
+ ? R.string.battery_usage_for_background_time
+ : R.string.battery_usage_for_total_time;
+ return mPrefContext.getString(resourceId, timeSequence);
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java b/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
index 0c7b4ab..c5c0522 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/ConvertUtils.java
@@ -219,7 +219,6 @@
.setPercentOfTotal(entry.mPercent)
.setDrainType(entry.getPowerComponentId())
.setForegroundUsageTimeInMs(entry.getTimeInForegroundMs())
- .setForegroundServiceUsageTimeInMs(entry.getTimeInForegroundServiceMs())
.setBackgroundUsageTimeInMs(entry.getTimeInBackgroundMs());
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
index 0a4ac7c..0f02d1c 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DataProcessor.java
@@ -21,6 +21,7 @@
import android.app.settings.SettingsEnums;
import android.content.ContentValues;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.BatteryConsumer;
@@ -86,6 +87,12 @@
static final double PERCENTAGE_OF_TOTAL_THRESHOLD = 1f;
@VisibleForTesting
static final int SELECTED_INDEX_ALL = BatteryChartViewModel.SELECTED_INDEX_ALL;
+ @VisibleForTesting
+ static final String CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER =
+ "CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER";
+
+ @VisibleForTesting
+ static long sFakeCurrentTimeMillis = 0;
/** A callback listener when battery usage loading async task is executed. */
public interface UsageMapAsyncResponse {
@@ -239,11 +246,12 @@
return resultMap;
}
Collections.sort(rawTimestampList);
- final List<Long> expectedTimestampList = getTimestampSlots(rawTimestampList);
+ final long currentTime = getCurrentTimeMillis();
+ final List<Long> expectedTimestampList = getTimestampSlots(rawTimestampList, currentTime);
final boolean isFromFullCharge =
isFromFullCharge(batteryHistoryMap.get(rawTimestampList.get(0)));
interpolateHistory(
- context, rawTimestampList, expectedTimestampList, isFromFullCharge,
+ context, rawTimestampList, expectedTimestampList, currentTime, isFromFullCharge,
batteryHistoryMap, resultMap);
Log.d(TAG, String.format("getHistoryMapWithExpectedTimestamps() size=%d in %d/ms",
resultMap.size(), (System.currentTimeMillis() - startTime)));
@@ -278,19 +286,16 @@
* between start and end two even hour values.
*/
@VisibleForTesting
- static List<Long> getTimestampSlots(final List<Long> rawTimestampList) {
+ static List<Long> getTimestampSlots(final List<Long> rawTimestampList, final long currentTime) {
final List<Long> timestampSlots = new ArrayList<>();
- final int rawTimestampListSize = rawTimestampList.size();
- // If timestamp number is smaller than 2, the following computation is not necessary.
- if (rawTimestampListSize < MIN_TIMESTAMP_DATA_SIZE) {
+ if (rawTimestampList.isEmpty()) {
return timestampSlots;
}
final long rawStartTimestamp = rawTimestampList.get(0);
- final long rawEndTimestamp = rawTimestampList.get(rawTimestampListSize - 1);
// No matter the start is from last full charge or 6 days ago, use the nearest even hour.
final long startTimestamp = getNearestEvenHourTimestamp(rawStartTimestamp);
- // Use the even hour before the raw end timestamp as the end.
- final long endTimestamp = getLastEvenHourBeforeTimestamp(rawEndTimestamp);
+ // Use the first even hour after the current time as the end.
+ final long endTimestamp = getFirstEvenHourAfterTimestamp(currentTime);
// If the start timestamp is later or equal the end one, return the empty list.
if (startTimestamp >= endTimestamp) {
return timestampSlots;
@@ -367,7 +372,7 @@
@VisibleForTesting
static long[] findNearestTimestamp(final List<Long> timestamps, final long target) {
- final long[] results = new long[] {Long.MIN_VALUE, Long.MAX_VALUE};
+ final long[] results = new long[]{Long.MIN_VALUE, Long.MAX_VALUE};
// Searches the nearest lower and upper timestamp value.
timestamps.forEach(timestamp -> {
if (timestamp <= target && timestamp > results[0]) {
@@ -393,7 +398,7 @@
}
/**
- * Returns whether currentSlot will be used in daily chart.
+ * Returns whether currentSlot will be used in daily chart.
*/
@VisibleForTesting
static boolean isForDailyChart(final boolean isStartOrEnd, final long currentSlot) {
@@ -451,10 +456,7 @@
@Nullable
static BatteryDiffData generateBatteryDiffData(
final Context context,
- @Nullable final List<BatteryEntry> batteryEntryList,
- final BatteryUsageStats batteryUsageStats) {
- final List<BatteryHistEntry> batteryHistEntryList =
- convertToBatteryHistEntry(batteryEntryList, batteryUsageStats);
+ final List<BatteryHistEntry> batteryHistEntryList) {
if (batteryHistEntryList == null || batteryHistEntryList.isEmpty()) {
Log.w(TAG, "batteryHistEntryList is null or empty in generateBatteryDiffData()");
return null;
@@ -466,20 +468,17 @@
userHandle != null ? userHandle.getIdentifier() : Integer.MIN_VALUE;
final List<BatteryDiffEntry> appEntries = new ArrayList<>();
final List<BatteryDiffEntry> systemEntries = new ArrayList<>();
- double totalConsumePower = 0f;
double consumePowerFromOtherUsers = 0f;
for (BatteryHistEntry entry : batteryHistEntryList) {
final boolean isFromOtherUsers = isConsumedFromOtherUsers(
currentUserId, workProfileUserId, entry);
- totalConsumePower += entry.mConsumePower;
if (isFromOtherUsers) {
consumePowerFromOtherUsers += entry.mConsumePower;
} else {
final BatteryDiffEntry currentBatteryDiffEntry = new BatteryDiffEntry(
context,
entry.mForegroundUsageTimeInMs,
- entry.mForegroundServiceUsageTimeInMs,
entry.mBackgroundUsageTimeInMs,
entry.mConsumePower,
entry.mForegroundUsageConsumePower,
@@ -503,7 +502,7 @@
return null;
}
- return new BatteryDiffData(appEntries, systemEntries, totalConsumePower);
+ return new BatteryDiffData(appEntries, systemEntries);
}
/**
@@ -532,7 +531,7 @@
final Map<Integer, BatteryDiffData> allUsageMap = new HashMap<>();
// Always construct the map whether the value is null or not.
allUsageMap.put(SELECTED_INDEX_ALL,
- getBatteryDiffDataFromBatteryStatsService(context));
+ generateBatteryDiffData(context, getBatteryHistListFromFromStatsService(context)));
resultMap.put(SELECTED_INDEX_ALL, allUsageMap);
// Compute the apps number before purge. Must put before purgeLowPercentageAndFakeData.
@@ -546,24 +545,33 @@
}
@Nullable
- private static BatteryDiffData getBatteryDiffDataFromBatteryStatsService(
+ private static List<BatteryHistEntry> getBatteryHistListFromFromStatsService(
final Context context) {
- BatteryDiffData batteryDiffData = null;
+ List<BatteryHistEntry> batteryHistEntryList = null;
try {
final BatteryUsageStats batteryUsageStats = getBatteryUsageStats(context);
final List<BatteryEntry> batteryEntryList =
generateBatteryEntryListFromBatteryUsageStats(context, batteryUsageStats);
- batteryDiffData = generateBatteryDiffData(context, batteryEntryList, batteryUsageStats);
+ batteryHistEntryList = convertToBatteryHistEntry(batteryEntryList, batteryUsageStats);
closeBatteryUsageStats(batteryUsageStats);
} catch (RuntimeException e) {
Log.e(TAG, "load batteryUsageStats:" + e);
}
- return batteryDiffData;
+ return batteryHistEntryList;
}
+ private static Map<String, BatteryHistEntry> getCurrentBatteryHistoryMapFromStatsService(
+ final Context context) {
+ final List<BatteryHistEntry> batteryHistEntryList =
+ getBatteryHistListFromFromStatsService(context);
+ return batteryHistEntryList == null ? new HashMap<>()
+ : batteryHistEntryList.stream().collect(Collectors.toMap(e -> e.getKey(), e -> e));
+ }
+
+ @VisibleForTesting
@Nullable
- private static List<BatteryHistEntry> convertToBatteryHistEntry(
+ static List<BatteryHistEntry> convertToBatteryHistEntry(
@Nullable final List<BatteryEntry> batteryEntryList,
final BatteryUsageStats batteryUsageStats) {
if (batteryEntryList == null || batteryEntryList.isEmpty()) {
@@ -573,16 +581,12 @@
return batteryEntryList.stream()
.filter(entry -> {
final long foregroundMs = entry.getTimeInForegroundMs();
- final long foregroundServiceMs = entry.getTimeInForegroundServiceMs();
final long backgroundMs = entry.getTimeInBackgroundMs();
return entry.getConsumedPower() > 0
|| (entry.getConsumedPower() == 0
- && (foregroundMs != 0 || foregroundServiceMs != 0
- || backgroundMs != 0));
+ && (foregroundMs != 0 || backgroundMs != 0));
})
- .map(entry -> ConvertUtils.convertToBatteryHistEntry(
- entry,
- batteryUsageStats))
+ .map(entry -> ConvertUtils.convertToBatteryHistEntry(entry, batteryUsageStats))
.collect(Collectors.toList());
}
@@ -594,6 +598,7 @@
Context context,
final List<Long> rawTimestampList,
final List<Long> expectedTimestampSlots,
+ final long currentTime,
final boolean isFromFullCharge,
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap,
final Map<Long, Map<String, BatteryHistEntry>> resultMap) {
@@ -614,6 +619,17 @@
final int expectedTimestampSlotsSize = expectedTimestampSlots.size();
for (int index = startIndex; index < expectedTimestampSlotsSize; index++) {
final long currentSlot = expectedTimestampSlots.get(index);
+ if (currentSlot > currentTime) {
+ // The slot timestamp is greater than the current time. Puts a placeholder first,
+ // then in the async task, loads the real time battery usage data from the battery
+ // stats service.
+ // If current time is odd hour, one placeholder is added. If the current hour is
+ // even hour, two placeholders are added. This is because the method
+ // insertHourlyUsageDiffDataPerSlot() requires continuing three hours data.
+ resultMap.put(currentSlot,
+ Map.of(CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER, EMPTY_BATTERY_HIST_ENTRY));
+ continue;
+ }
final boolean isStartOrEnd = index == 0 || index == expectedTimestampSlotsSize - 1;
interpolateHistoryForSlot(
context, currentSlot, rawTimestampList, batteryHistoryMap, resultMap,
@@ -699,14 +715,9 @@
if (lowerEntry != null) {
final boolean invalidForegroundUsageTime =
lowerEntry.mForegroundUsageTimeInMs > upperEntry.mForegroundUsageTimeInMs;
- final boolean invalidForegroundServiceUsageTime =
- lowerEntry.mForegroundServiceUsageTimeInMs
- > upperEntry.mForegroundServiceUsageTimeInMs;
final boolean invalidBackgroundUsageTime =
lowerEntry.mBackgroundUsageTimeInMs > upperEntry.mBackgroundUsageTimeInMs;
- if (invalidForegroundUsageTime
- || invalidForegroundServiceUsageTime
- || invalidBackgroundUsageTime) {
+ if (invalidForegroundUsageTime || invalidBackgroundUsageTime) {
newHistEntryMap.put(entryKey, upperEntry);
log(context, "abnormal reset condition is found", currentSlot, upperEntry);
continue;
@@ -741,6 +752,13 @@
}
/**
+ * @return Returns the fist even hour timestamp after the given timestamp.
+ */
+ private static long getFirstEvenHourAfterTimestamp(long rawTimestamp) {
+ return getLastEvenHourBeforeTimestamp(rawTimestamp + DateUtils.HOUR_IN_MILLIS * 2);
+ }
+
+ /**
* @return Returns the last even hour timestamp before the given timestamp.
*/
private static long getLastEvenHourBeforeTimestamp(long rawTimestamp) {
@@ -817,6 +835,12 @@
+ utcToLocalTime(context, timestamp));
return null;
}
+ // The current time battery history hasn't been loaded yet, returns the current battery
+ // level.
+ if (entryMap.containsKey(CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER)) {
+ final Intent intent = BatteryUtils.getBatteryIntent(context);
+ return BatteryStatus.getBatteryLevel(intent);
+ }
// Averages the battery level in each time slot to avoid corner conditions.
float batteryLevelCounter = 0;
for (BatteryHistEntry entry : entryMap.values()) {
@@ -921,7 +945,6 @@
allBatteryHistEntryKeys.addAll(nextBatteryHistMap.keySet());
allBatteryHistEntryKeys.addAll(nextTwoBatteryHistMap.keySet());
- double totalConsumePower = 0.0;
double consumePowerFromOtherUsers = 0f;
// Calculates all packages diff usage data in a specific time slot.
for (String key : allBatteryHistEntryKeys) {
@@ -937,11 +960,6 @@
currentEntry.mForegroundUsageTimeInMs,
nextEntry.mForegroundUsageTimeInMs,
nextTwoEntry.mForegroundUsageTimeInMs);
- long foregroundServiceUsageTimeInMs =
- getDiffValue(
- currentEntry.mForegroundServiceUsageTimeInMs,
- nextEntry.mForegroundServiceUsageTimeInMs,
- nextTwoEntry.mForegroundServiceUsageTimeInMs);
long backgroundUsageTimeInMs =
getDiffValue(
currentEntry.mBackgroundUsageTimeInMs,
@@ -974,7 +992,6 @@
nextTwoEntry.mCachedUsageConsumePower);
// Excludes entry since we don't have enough data to calculate.
if (foregroundUsageTimeInMs == 0
- && foregroundServiceUsageTimeInMs == 0
&& backgroundUsageTimeInMs == 0
&& consumePower == 0) {
continue;
@@ -986,7 +1003,6 @@
}
// Forces refine the cumulative value since it may introduce deviation error since we
// will apply the interpolation arithmetic.
- // TODO: update this value after the new API for foreground service is completed.
final float totalUsageTimeInMs =
foregroundUsageTimeInMs + backgroundUsageTimeInMs;
if (totalUsageTimeInMs > TOTAL_HOURLY_TIME_THRESHOLD) {
@@ -999,8 +1015,6 @@
}
foregroundUsageTimeInMs =
Math.round(foregroundUsageTimeInMs * ratio);
- foregroundServiceUsageTimeInMs =
- Math.round(foregroundServiceUsageTimeInMs * ratio);
backgroundUsageTimeInMs =
Math.round(backgroundUsageTimeInMs * ratio);
consumePower = consumePower * ratio;
@@ -1009,7 +1023,6 @@
backgroundUsageConsumePower = backgroundUsageConsumePower * ratio;
cachedUsageConsumePower = cachedUsageConsumePower * ratio;
}
- totalConsumePower += consumePower;
final boolean isFromOtherUsers = isConsumedFromOtherUsers(
currentUserId, workProfileUserId, selectedBatteryEntry);
@@ -1019,7 +1032,6 @@
final BatteryDiffEntry currentBatteryDiffEntry = new BatteryDiffEntry(
context,
foregroundUsageTimeInMs,
- foregroundServiceUsageTimeInMs,
backgroundUsageTimeInMs,
consumePower,
foregroundUsageConsumePower,
@@ -1043,9 +1055,7 @@
return null;
}
- final BatteryDiffData resultDiffData =
- new BatteryDiffData(appEntries, systemEntries, totalConsumePower);
- return resultDiffData;
+ return new BatteryDiffData(appEntries, systemEntries);
}
private static boolean isConsumedFromOtherUsers(
@@ -1060,7 +1070,6 @@
@Nullable
private static BatteryDiffData getAccumulatedUsageDiffData(
final Collection<BatteryDiffData> diffEntryListData) {
- double totalConsumePower = 0f;
final Map<String, BatteryDiffEntry> diffEntryMap = new HashMap<>();
final List<BatteryDiffEntry> appEntries = new ArrayList<>();
final List<BatteryDiffEntry> systemEntries = new ArrayList<>();
@@ -1071,18 +1080,14 @@
}
for (BatteryDiffEntry entry : diffEntryList.getAppDiffEntryList()) {
computeUsageDiffDataPerEntry(entry, diffEntryMap);
- totalConsumePower += entry.mConsumePower;
}
for (BatteryDiffEntry entry : diffEntryList.getSystemDiffEntryList()) {
computeUsageDiffDataPerEntry(entry, diffEntryMap);
- totalConsumePower += entry.mConsumePower;
}
}
final Collection<BatteryDiffEntry> diffEntryList = diffEntryMap.values();
for (BatteryDiffEntry entry : diffEntryList) {
- // Sets total daily consume power data into all BatteryDiffEntry.
- entry.setTotalConsumePower(totalConsumePower);
if (entry.isSystemEntry()) {
systemEntries.add(entry);
} else {
@@ -1105,8 +1110,6 @@
// Sums up some field data into the existing one.
oldBatteryDiffEntry.mForegroundUsageTimeInMs +=
entry.mForegroundUsageTimeInMs;
- oldBatteryDiffEntry.mForegroundServiceUsageTimeInMs +=
- entry.mForegroundServiceUsageTimeInMs;
oldBatteryDiffEntry.mBackgroundUsageTimeInMs +=
entry.mBackgroundUsageTimeInMs;
oldBatteryDiffEntry.mConsumePower += entry.mConsumePower;
@@ -1227,14 +1230,11 @@
final BatteryConsumer deviceConsumer = batteryUsageStats.getAggregateBatteryConsumer(
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE);
- final BatteryConsumer appsConsumer = batteryUsageStats.getAggregateBatteryConsumer(
- BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS);
for (int componentId = 0; componentId < BatteryConsumer.POWER_COMPONENT_COUNT;
componentId++) {
results.add(new BatteryEntry(context, componentId,
deviceConsumer.getConsumedPower(componentId),
- appsConsumer.getConsumedPower(componentId),
deviceConsumer.getUsageDurationMillis(componentId)));
}
@@ -1244,8 +1244,7 @@
componentId++) {
results.add(new BatteryEntry(context, componentId,
deviceConsumer.getCustomPowerComponentName(componentId),
- deviceConsumer.getConsumedPowerForCustomComponent(componentId),
- appsConsumer.getConsumedPowerForCustomComponent(componentId)));
+ deviceConsumer.getConsumedPowerForCustomComponent(componentId)));
}
final List<UserBatteryConsumer> userBatteryConsumers =
@@ -1404,7 +1403,6 @@
final BatteryDiffEntry batteryDiffEntry = new BatteryDiffEntry(
context,
/*foregroundUsageTimeInMs=*/ 0,
- /*foregroundServiceUsageTimeInMs=*/ 0,
/*backgroundUsageTimeInMs=*/ 0,
consumePower,
/*foregroundUsageConsumePower=*/ 0,
@@ -1415,6 +1413,10 @@
return batteryDiffEntry;
}
+ private static long getCurrentTimeMillis() {
+ return sFakeCurrentTimeMillis > 0 ? sFakeCurrentTimeMillis : System.currentTimeMillis();
+ }
+
private static void logAppCountMetrics(
Context context, final int countOfAppBeforePurge, final int countOfAppAfterPurge) {
context = context.getApplicationContext();
@@ -1486,6 +1488,17 @@
return null;
}
final long startTime = System.currentTimeMillis();
+ // Loads the current battery usage data from the battery stats service and replaces the
+ // placeholder in mBatteryHistoryMap.
+ Map<String, BatteryHistEntry> currentBatteryHistoryMap =
+ getCurrentBatteryHistoryMapFromStatsService(mApplicationContext);
+ for (Map.Entry<Long, Map<String, BatteryHistEntry>> mapEntry
+ : mBatteryHistoryMap.entrySet()) {
+ if (mapEntry.getValue().containsKey(CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER)) {
+ mapEntry.setValue(currentBatteryHistoryMap);
+ }
+ }
+
final Map<Integer, Map<Integer, BatteryDiffData>> batteryUsageMap =
getBatteryUsageMap(
mApplicationContext, mHourlyBatteryLevelsPerDay, mBatteryHistoryMap);
diff --git a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
index fdcbb4a..8ff802d 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/DatabaseUtils.java
@@ -165,20 +165,16 @@
batteryEntryList.stream()
.filter(entry -> {
final long foregroundMs = entry.getTimeInForegroundMs();
- final long foregroundServiceMs = entry.getTimeInForegroundServiceMs();
final long backgroundMs = entry.getTimeInBackgroundMs();
if (entry.getConsumedPower() == 0
&& (foregroundMs != 0
- || foregroundServiceMs != 0
|| backgroundMs != 0)) {
Log.w(TAG, String.format(
- "no consumed power but has running time for %s time=%d|%d|%d",
- entry.getLabel(), foregroundMs, foregroundServiceMs,
- backgroundMs));
+ "no consumed power but has running time for %s time=%d|%d",
+ entry.getLabel(), foregroundMs, backgroundMs));
}
return entry.getConsumedPower() != 0
|| foregroundMs != 0
- || foregroundServiceMs != 0
|| backgroundMs != 0;
})
.forEach(entry -> valuesList.add(
diff --git a/src/com/android/settings/fuelgauge/batteryusage/ExpandDividerPreference.java b/src/com/android/settings/fuelgauge/batteryusage/ExpandDividerPreference.java
deleted file mode 100644
index 8af842b..0000000
--- a/src/com/android/settings/fuelgauge/batteryusage/ExpandDividerPreference.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settings.fuelgauge.batteryusage;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-
-import com.android.settings.R;
-
-/** A preference for expandable section divider. */
-public class ExpandDividerPreference extends Preference {
- private static final String TAG = "ExpandDividerPreference";
- @VisibleForTesting
- static final String PREFERENCE_KEY = "expandable_divider";
-
- @VisibleForTesting
- TextView mTextView;
- @VisibleForTesting
- ImageView mImageView;
- private OnExpandListener mOnExpandListener;
-
- private boolean mIsExpanded = false;
- private String mTitleContent = null;
-
- /** A callback listener for expand state is changed by users. */
- public interface OnExpandListener {
- /** Callback function for expand state is changed by users. */
- void onExpand(boolean isExpanded);
- }
-
- public ExpandDividerPreference(Context context) {
- this(context, /*attrs=*/ null);
- }
-
- public ExpandDividerPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- setLayoutResource(R.layout.preference_expand_divider);
- setKey(PREFERENCE_KEY);
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder view) {
- super.onBindViewHolder(view);
- mTextView = (TextView) view.findViewById(R.id.expand_title);
- mImageView = (ImageView) view.findViewById(R.id.expand_icon);
- refreshState();
- }
-
- @Override
- public void onClick() {
- setIsExpanded(!mIsExpanded);
- if (mOnExpandListener != null) {
- mOnExpandListener.onExpand(mIsExpanded);
- }
- }
-
- void setTitle(final String titleContent) {
- mTitleContent = titleContent;
- refreshState();
- }
-
- void setIsExpanded(boolean isExpanded) {
- mIsExpanded = isExpanded;
- refreshState();
- }
-
- void setOnExpandListener(OnExpandListener listener) {
- mOnExpandListener = listener;
- }
-
- private void refreshState() {
- if (mImageView != null) {
- mImageView.setImageResource(mIsExpanded
- ? R.drawable.ic_settings_expand_less
- : R.drawable.ic_settings_expand_more);
- }
- if (mTextView != null) {
- mTextView.setText(mTitleContent);
- }
- }
-}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java
index 2dba3c2..c7cf70e 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/PowerUsageAdvanced.java
@@ -34,8 +34,6 @@
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.fuelgauge.BatteryBroadcastReceiver;
-import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
-import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
@@ -50,8 +48,7 @@
public class PowerUsageAdvanced extends PowerUsageBase {
private static final String TAG = "AdvancedBatteryUsage";
private static final String KEY_REFRESH_TYPE = "refresh_type";
- private static final String KEY_BATTERY_GRAPH = "battery_graph";
- private static final String KEY_APP_LIST = "app_list";
+ private static final String KEY_BATTERY_CHART = "battery_chart";
@VisibleForTesting
BatteryHistoryPreference mHistPref;
@@ -62,7 +59,6 @@
new BatteryHistoryLoaderCallbacks();
private boolean mIsChartDataLoaded = false;
- private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
private BatteryChartPreferenceController mBatteryChartPreferenceController;
private final ContentObserver mBatteryObserver =
@@ -79,9 +75,7 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- final Context context = getContext();
- refreshFeatureFlag(context);
- mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_GRAPH);
+ mHistPref = findPreference(KEY_BATTERY_CHART);
setBatteryChartPreferenceController();
}
@@ -131,12 +125,19 @@
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
- refreshFeatureFlag(context);
final List<AbstractPreferenceController> controllers = new ArrayList<>();
mBatteryChartPreferenceController =
- new BatteryChartPreferenceController(context, KEY_APP_LIST,
- getSettingsLifecycle(), (SettingsActivity) getActivity(), this);
+ new BatteryChartPreferenceController(
+ context, getSettingsLifecycle(), (SettingsActivity) getActivity());
+ BatteryUsageBreakdownController batteryUsageBreakdownController =
+ new BatteryUsageBreakdownController(
+ context, getSettingsLifecycle(), (SettingsActivity) getActivity(), this);
+
+ mBatteryChartPreferenceController.setOnBatteryUsageUpdatedListener(
+ batteryUsageBreakdownController::handleBatteryUsageUpdated);
+
controllers.add(mBatteryChartPreferenceController);
+ controllers.add(batteryUsageBreakdownController);
setBatteryChartPreferenceController();
return controllers;
}
@@ -169,13 +170,6 @@
}
}
- private void refreshFeatureFlag(Context context) {
- if (mPowerUsageFeatureProvider == null) {
- mPowerUsageFeatureProvider = FeatureFactory.getFactory(context)
- .getPowerUsageFeatureProvider(context);
- }
- }
-
private void setBatteryChartPreferenceController() {
if (mHistPref != null && mBatteryChartPreferenceController != null) {
mHistPref.setChartPreferenceController(mBatteryChartPreferenceController);
@@ -196,8 +190,10 @@
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
- controllers.add(new BatteryChartPreferenceController(context,
- KEY_APP_LIST, null /* lifecycle */, null /* activity */,
+ controllers.add(new BatteryChartPreferenceController(
+ context, null /* lifecycle */, null /* activity */));
+ controllers.add(new BatteryUsageBreakdownController(
+ context, null /* lifecycle */, null /* activity */,
null /* fragment */));
return controllers;
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/TabPreference.java b/src/com/android/settings/fuelgauge/batteryusage/TabPreference.java
new file mode 100644
index 0000000..517e01c
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batteryusage/TabPreference.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge.batteryusage;
+
+import android.content.Context;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+import androidx.viewpager2.adapter.FragmentStateAdapter;
+import androidx.viewpager2.widget.ViewPager2;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+
+import com.google.android.material.tabs.TabLayout;
+import com.google.android.material.tabs.TabLayoutMediator;
+
+/** A preference which contains a tab selection. */
+public class TabPreference extends Preference {
+ private static final String TAG = "TabPreference";
+
+ private Fragment mRootFragment;
+ private ViewPager2 mViewPager;
+ private ViewPager2.OnPageChangeCallback mOnPageChangeCallback;
+
+ @VisibleForTesting
+ String[] mTabTitles;
+ @VisibleForTesting
+ int mSavedTabPosition;
+ @VisibleForTesting
+ TabLayout mTabLayout;
+
+ public TabPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setLayoutResource(R.layout.preference_tab);
+ }
+
+ void initializeTabs(Fragment rootFragment, String[] tabTitles) {
+ mRootFragment = rootFragment;
+ mTabTitles = tabTitles;
+ }
+
+ void setOnPageChangeCallback(ViewPager2.OnPageChangeCallback callback) {
+ mOnPageChangeCallback = callback;
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder view) {
+ super.onBindViewHolder(view);
+ if (mViewPager != null && mTabLayout != null) {
+ return;
+ }
+
+ mViewPager = (ViewPager2) view.findViewById(R.id.view_pager);
+ mViewPager.setAdapter(new FragmentAdapter(mRootFragment, mTabTitles.length));
+ mViewPager.setUserInputEnabled(false);
+ if (mOnPageChangeCallback != null) {
+ mViewPager.registerOnPageChangeCallback(mOnPageChangeCallback);
+ }
+
+ mTabLayout = (TabLayout) view.findViewById(R.id.tabs);
+ new TabLayoutMediator(
+ mTabLayout, mViewPager, /* autoRefresh= */ true, /* smoothScroll= */ false,
+ (tab, position) -> tab.setText(mTabTitles[position])).attach();
+ mTabLayout.getTabAt(mSavedTabPosition).select();
+ }
+
+ @Override
+ public void onDetached() {
+ super.onDetached();
+ if (mOnPageChangeCallback != null) {
+ mViewPager.unregisterOnPageChangeCallback(mOnPageChangeCallback);
+ }
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ Log.d(TAG, "onSaveInstanceState() tabPosition=" + mTabLayout.getSelectedTabPosition());
+ return new SavedState(super.onSaveInstanceState(), mTabLayout.getSelectedTabPosition());
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state == null || !state.getClass().equals(SavedState.class)) {
+ super.onRestoreInstanceState(state);
+ return;
+ }
+ SavedState savedState = (SavedState) state;
+ super.onRestoreInstanceState(savedState.getSuperState());
+ mSavedTabPosition = savedState.getTabPosition();
+ Log.d(TAG, "onRestoreInstanceState() tabPosition=" + savedState.getTabPosition());
+ }
+
+ @VisibleForTesting
+ static class SavedState extends BaseSavedState {
+ private int mTabPosition;
+
+ SavedState(Parcelable superState, int tabPosition) {
+ super(superState);
+ mTabPosition = tabPosition;
+ }
+
+ int getTabPosition() {
+ return mTabPosition;
+ }
+ }
+
+ private static class FragmentAdapter extends FragmentStateAdapter {
+ private final int mItemCount;
+ private final Fragment[] mItemFragments;
+
+ FragmentAdapter(@NonNull Fragment rootFragment, int itemCount) {
+ super(rootFragment);
+ mItemCount = itemCount;
+ mItemFragments = new Fragment[mItemCount];
+ for (int i = 0; i < mItemCount; i++) {
+ // Empty tab pages.
+ mItemFragments[i] = new Fragment();
+ }
+ }
+
+ @NonNull
+ @Override
+ public Fragment createFragment(int position) {
+ return mItemFragments[position];
+ }
+
+ @Override
+ public int getItemCount() {
+ return mItemCount;
+ }
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/protos/fuelgauge_usage_state.proto b/src/com/android/settings/fuelgauge/protos/fuelgauge_usage_state.proto
index 813344b..b9b05a3 100644
--- a/src/com/android/settings/fuelgauge/protos/fuelgauge_usage_state.proto
+++ b/src/com/android/settings/fuelgauge/protos/fuelgauge_usage_state.proto
@@ -31,10 +31,9 @@
optional double percent_of_total = 12;
optional int32 drain_type = 13;
optional int64 foreground_usage_time_in_ms = 14;
- optional int64 foreground_service_usage_time_in_ms = 15;
- optional int64 background_usage_time_in_ms = 16;
- optional double foreground_usage_consume_power = 17;
- optional double foreground_service_usage_consume_power = 18;
- optional double background_usage_consume_power = 19;
- optional double cached_usage_consume_power = 20;
+ optional int64 background_usage_time_in_ms = 15;
+ optional double foreground_usage_consume_power = 16;
+ optional double foreground_service_usage_consume_power = 17;
+ optional double background_usage_consume_power = 18;
+ optional double cached_usage_consume_power = 19;
}
\ No newline at end of file
diff --git a/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java b/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java
index ecbcb30..0ea9ffb 100644
--- a/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java
+++ b/src/com/android/settings/location/RecentLocationAccessSeeAllFragment.java
@@ -15,6 +15,7 @@
*/
package com.android.settings.location;
+import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
import android.provider.DeviceConfig;
@@ -24,7 +25,6 @@
import android.view.MenuItem;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
@@ -47,7 +47,7 @@
@Override
public int getMetricsCategory() {
- return MetricsEvent.RECENT_LOCATION_REQUESTS_ALL;
+ return SettingsEnums.LOCATION_RECENT_ACCESS_ALL;
}
@Override
diff --git a/src/com/android/settings/location/RecentLocationRequestSeeAllFragment.java b/src/com/android/settings/location/RecentLocationRequestSeeAllFragment.java
deleted file mode 100644
index 7fd6643..0000000
--- a/src/com/android/settings/location/RecentLocationRequestSeeAllFragment.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settings.location;
-
-import android.content.Context;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.R;
-import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
-
-/** @deprecated Use {@link RecentLocationAccessSeeAllFragment} instead. */
-@Deprecated
-public class RecentLocationRequestSeeAllFragment extends DashboardFragment {
- private static final String TAG = "RecentLocationReqAll";
- public static final String PATH =
- "com.android.settings.location.RecentLocationRequestSeeAllFragment";
-
- private static final int MENU_SHOW_SYSTEM = Menu.FIRST + 1;
- private static final int MENU_HIDE_SYSTEM = Menu.FIRST + 2;
-
- private boolean mShowSystem = false;
- private MenuItem mShowSystemMenu;
- private MenuItem mHideSystemMenu;
- private RecentLocationRequestSeeAllPreferenceController mController;
-
- @Override
- public int getMetricsCategory() {
- return MetricsEvent.RECENT_LOCATION_REQUESTS_ALL;
- }
-
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
- final int profileType = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE);
-
- mController = use(RecentLocationRequestSeeAllPreferenceController.class);
- mController.init(this);
- if (profileType != 0) {
- mController.setProfileType(profileType);
- }
- }
-
- @Override
- protected int getPreferenceScreenResId() {
- return R.xml.location_recent_requests_see_all;
- }
-
- @Override
- protected String getLogTag() {
- return TAG;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem menuItem) {
- switch (menuItem.getItemId()) {
- case MENU_SHOW_SYSTEM:
- case MENU_HIDE_SYSTEM:
- mShowSystem = menuItem.getItemId() == MENU_SHOW_SYSTEM;
- updateMenu();
- if (mController != null) {
- mController.setShowSystem(mShowSystem);
- }
- return true;
- default:
- return super.onOptionsItemSelected(menuItem);
- }
- }
-
- private void updateMenu() {
- mShowSystemMenu.setVisible(!mShowSystem);
- mHideSystemMenu.setVisible(mShowSystem);
- }
-
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- super.onCreateOptionsMenu(menu, inflater);
- mShowSystemMenu = menu.add(Menu.NONE, MENU_SHOW_SYSTEM, Menu.NONE,
- R.string.menu_show_system);
- mHideSystemMenu = menu.add(Menu.NONE, MENU_HIDE_SYSTEM, Menu.NONE,
- R.string.menu_hide_system);
- updateMenu();
- }
-}
diff --git a/src/com/android/settings/network/BluetoothWiFiResetPreferenceController.java b/src/com/android/settings/network/BluetoothWiFiResetPreferenceController.java
new file mode 100644
index 0000000..6eb470b
--- /dev/null
+++ b/src/com/android/settings/network/BluetoothWiFiResetPreferenceController.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.network;
+
+import android.app.ProgressDialog;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Looper;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.Toast;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.appcompat.app.AlertDialog;
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.ResetNetworkRequest;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * This is to show a preference regarding resetting Bluetooth and Wi-Fi.
+ */
+public class BluetoothWiFiResetPreferenceController extends BasePreferenceController
+ implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
+
+ private static final String TAG = "BtWiFiResetPreferenceController";
+
+ private final NetworkResetRestrictionChecker mRestrictionChecker;
+
+ private DialogInterface mResetDialog;
+ private ProgressDialog mProgressDialog;
+ private ExecutorService mExecutorService;
+
+ /**
+ * Constructer.
+ * @param context Context
+ * @param preferenceKey is the key for Preference
+ */
+ public BluetoothWiFiResetPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+
+ // restriction check
+ mRestrictionChecker = new NetworkResetRestrictionChecker(context);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return mRestrictionChecker.hasUserRestriction() ?
+ CONDITIONALLY_UNAVAILABLE : AVAILABLE;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+ return false;
+ }
+ buildResetDialog(preference);
+ return true;
+ }
+
+ /**
+ * This is a pop-up dialog showing detail of this reset option.
+ */
+ void buildResetDialog(Preference preference) {
+ if (mResetDialog != null) {
+ return;
+ }
+ mResetDialog = new AlertDialog.Builder(mContext)
+ .setTitle(R.string.reset_bluetooth_wifi_title)
+ .setMessage(R.string.reset_bluetooth_wifi_desc)
+ .setPositiveButton(R.string.reset_bluetooth_wifi_button_text, this)
+ .setNegativeButton(R.string.cancel, null /* OnClickListener */)
+ .setOnDismissListener(this)
+ .show();
+ }
+
+ public void onDismiss(DialogInterface dialog) {
+ if (mResetDialog == dialog) {
+ mResetDialog = null;
+ }
+ }
+
+ /**
+ * User pressed confirmation button, for starting reset operation.
+ */
+ public void onClick(DialogInterface dialog, int which) {
+ if (mResetDialog != dialog) {
+ return;
+ }
+
+ // User confirm the reset operation
+ MetricsFeatureProvider provider = FeatureFactory.getFactory(mContext)
+ .getMetricsFeatureProvider();
+ provider.action(mContext, SettingsEnums.RESET_BLUETOOTH_WIFI_CONFIRM, true);
+
+ // Non-cancelable progress dialog
+ mProgressDialog = getProgressDialog(mContext);
+ mProgressDialog.show();
+
+ // Run reset in background thread
+ mExecutorService = Executors.newSingleThreadExecutor();
+ mExecutorService.execute(() -> {
+ final AtomicReference<Exception> exceptionDuringReset =
+ new AtomicReference<Exception>();
+ try {
+ resetOperation().run();
+ } catch (Exception exception) {
+ exceptionDuringReset.set(exception);
+ }
+ mContext.getMainExecutor().execute(() -> endOfReset(exceptionDuringReset.get()));
+ });
+ }
+
+ @VisibleForTesting
+ protected ProgressDialog getProgressDialog(Context context) {
+ final ProgressDialog progressDialog = new ProgressDialog(context);
+ progressDialog.setIndeterminate(true);
+ progressDialog.setCancelable(false);
+ progressDialog.setMessage(
+ context.getString(R.string.main_clear_progress_text));
+ return progressDialog;
+ }
+
+ @VisibleForTesting
+ protected Runnable resetOperation() throws Exception {
+ if (SubscriptionUtil.isSimHardwareVisible(mContext)) {
+ return new ResetNetworkRequest(
+ ResetNetworkRequest.RESET_WIFI_MANAGER |
+ ResetNetworkRequest.RESET_WIFI_P2P_MANAGER |
+ ResetNetworkRequest.RESET_BLUETOOTH_MANAGER)
+ .toResetNetworkOperationBuilder(mContext, Looper.getMainLooper())
+ .build();
+ }
+
+ /**
+ * For device without SIMs visible to the user
+ */
+ return new ResetNetworkRequest(
+ ResetNetworkRequest.RESET_CONNECTIVITY_MANAGER |
+ ResetNetworkRequest.RESET_VPN_MANAGER |
+ ResetNetworkRequest.RESET_WIFI_MANAGER |
+ ResetNetworkRequest.RESET_WIFI_P2P_MANAGER |
+ ResetNetworkRequest.RESET_BLUETOOTH_MANAGER)
+ .toResetNetworkOperationBuilder(mContext, Looper.getMainLooper())
+ .resetTelephonyAndNetworkPolicyManager(ResetNetworkRequest.ALL_SUBSCRIPTION_ID)
+ .build();
+ }
+
+ @VisibleForTesting
+ protected void endOfReset(Exception exceptionDuringReset) {
+ if (mExecutorService != null) {
+ mExecutorService.shutdown();
+ mExecutorService = null;
+ }
+ if (mProgressDialog != null) {
+ mProgressDialog.dismiss();
+ mProgressDialog = null;
+ }
+ if (exceptionDuringReset == null) {
+ Toast.makeText(mContext, R.string.reset_bluetooth_wifi_complete_toast,
+ Toast.LENGTH_SHORT).show();
+ } else {
+ Log.e(TAG, "Exception during reset", exceptionDuringReset);
+ }
+ }
+}
diff --git a/src/com/android/settings/network/MobileNetworkSummaryController.java b/src/com/android/settings/network/MobileNetworkSummaryController.java
index 0bb1bb3..0e2ea09 100644
--- a/src/com/android/settings/network/MobileNetworkSummaryController.java
+++ b/src/com/android/settings/network/MobileNetworkSummaryController.java
@@ -37,7 +37,7 @@
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.network.telephony.MobileNetworkUtils;
import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.widget.AddPreference;
+import com.android.settingslib.RestrictedPreference;
import com.android.settingslib.Utils;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -58,7 +58,7 @@
private final MetricsFeatureProvider mMetricsFeatureProvider;
private UserManager mUserManager;
- private AddPreference mPreference;
+ private RestrictedPreference mPreference;
private MobileNetworkRepository mMobileNetworkRepository;
private List<SubscriptionInfoEntity> mSubInfoEntityList;
@@ -89,6 +89,7 @@
mUserManager = context.getSystemService(UserManager.class);
mLifecycleOwner = lifecycleOwner;
mMobileNetworkRepository = MobileNetworkRepository.create(context, this);
+ mIsAirplaneModeOn = mMobileNetworkRepository.isAirplaneModeOn();
if (lifecycle != null) {
lifecycle.addObserver(this);
}
@@ -152,7 +153,6 @@
private void initPreference() {
refreshSummary(mPreference);
mPreference.setOnPreferenceClickListener(null);
- mPreference.setOnAddClickListener(null);
mPreference.setFragment(null);
mPreference.setEnabled(!mIsAirplaneModeOn);
}
@@ -179,33 +179,7 @@
return;
}
- // We have one or more existing subscriptions, so we want the plus button if eSIM is
- // supported.
- if (MobileNetworkUtils.showEuiccSettingsDetecting(mContext)) {
- mPreference.setAddWidgetEnabled(!mIsAirplaneModeOn);
- mPreference.setOnAddClickListener(p -> {
- logPreferenceClick(p);
- startAddSimFlow();
- });
- }
-
- if (mSubInfoEntityList.size() == 1) {
- mPreference.setOnPreferenceClickListener((Preference pref) -> {
- logPreferenceClick(pref);
- SubscriptionInfoEntity info = mSubInfoEntityList.get(0);
- if (info.isEmbedded || mUiccInfoEntityList.get(0).isActive
- || mMobileNetworkInfoEntityList.get(0).showToggleForPhysicalSim) {
- MobileNetworkUtils.launchMobileNetworkSettings(mContext, info);
- return true;
- }
-
- SubscriptionUtil.startToggleSubscriptionDialogActivity(
- mContext, Integer.parseInt(info.subId), true);
- return true;
- });
- } else {
- mPreference.setFragment(MobileNetworkListFragment.class.getCanonicalName());
- }
+ mPreference.setFragment(MobileNetworkListFragment.class.getCanonicalName());
}
@Override
@@ -221,8 +195,10 @@
@Override
public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
- mIsAirplaneModeOn = airplaneModeEnabled;
- update();
+ if (mIsAirplaneModeOn != airplaneModeEnabled) {
+ mIsAirplaneModeOn = airplaneModeEnabled;
+ update();
+ }
}
@Override
@@ -239,14 +215,19 @@
@Override
public void onAllUiccInfoChanged(List<UiccInfoEntity> uiccInfoEntityList) {
- mUiccInfoEntityList = uiccInfoEntityList;
- update();
+ if (DataServiceUtils.shouldUpdateEntityList(mUiccInfoEntityList, uiccInfoEntityList)) {
+ mUiccInfoEntityList = uiccInfoEntityList;
+ update();
+ }
}
@Override
public void onAllMobileNetworkInfoChanged(
List<MobileNetworkInfoEntity> mobileNetworkInfoEntityList) {
- mMobileNetworkInfoEntityList = mobileNetworkInfoEntityList;
- update();
+ if (DataServiceUtils.shouldUpdateEntityList(mMobileNetworkInfoEntityList,
+ mobileNetworkInfoEntityList)) {
+ mMobileNetworkInfoEntityList = mobileNetworkInfoEntityList;
+ update();
+ }
}
}
diff --git a/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java b/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java
index 772db45..ab80f6a 100644
--- a/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java
+++ b/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java
@@ -84,7 +84,7 @@
@Override
public int getMetricsCategory() {
- return SettingsEnums.ACTION_UNKNOWN;
+ return SettingsEnums.NETWORK_PROVIDER_CALLS_SMS;
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
diff --git a/src/com/android/settings/network/NetworkResetPreferenceController.java b/src/com/android/settings/network/NetworkResetPreferenceController.java
index 58a5383..8842c61 100644
--- a/src/com/android/settings/network/NetworkResetPreferenceController.java
+++ b/src/com/android/settings/network/NetworkResetPreferenceController.java
@@ -19,6 +19,7 @@
import android.content.Context;
import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.network.SubscriptionUtil;
import com.android.settingslib.core.AbstractPreferenceController;
public class NetworkResetPreferenceController extends AbstractPreferenceController
@@ -33,7 +34,8 @@
@Override
public boolean isAvailable() {
- return !mRestrictionChecker.hasUserRestriction();
+ return (SubscriptionUtil.isSimHardwareVisible(mContext) &&
+ (!mRestrictionChecker.hasUserRestriction()));
}
@Override
diff --git a/src/com/android/settings/notification/MediaVolumePreferenceController.java b/src/com/android/settings/notification/MediaVolumePreferenceController.java
index 0ddba08..8c5cf21 100644
--- a/src/com/android/settings/notification/MediaVolumePreferenceController.java
+++ b/src/com/android/settings/notification/MediaVolumePreferenceController.java
@@ -93,7 +93,8 @@
@VisibleForTesting
boolean isSupportEndItem() {
- return getWorker() != null && getWorker().isBroadcastSupported() && isConnectedBLEDevice();
+ return getWorker() != null && getWorker().isBroadcastSupported()
+ && (getWorker().isDeviceBroadcasting() || isConnectedBLEDevice());
}
private boolean isConnectedBLEDevice() {
diff --git a/src/com/android/settings/privacy/PrivacyControlsFragment.java b/src/com/android/settings/privacy/PrivacyControlsFragment.java
index 1d9a4712..e40ed94 100644
--- a/src/com/android/settings/privacy/PrivacyControlsFragment.java
+++ b/src/com/android/settings/privacy/PrivacyControlsFragment.java
@@ -45,7 +45,7 @@
@Override
public int getMetricsCategory() {
- return SettingsEnums.TOP_LEVEL_PRIVACY;
+ return SettingsEnums.PRIVACY_CONTROLS;
}
@Override
diff --git a/src/com/android/settings/security/MemtagHelper.java b/src/com/android/settings/security/MemtagHelper.java
index c891eb2..b3e24e4 100644
--- a/src/com/android/settings/security/MemtagHelper.java
+++ b/src/com/android/settings/security/MemtagHelper.java
@@ -32,6 +32,13 @@
"persist.device_config.memory_safety_native.bootloader_override"));
}
+ private static boolean isForcedOn() {
+ return "force_on"
+ .equals(
+ SystemProperties.get(
+ "persist.device_config.memory_safety_native.bootloader_override"));
+ }
+
public static boolean isChecked() {
String modes[] = SystemProperties.get("arm64.memtag.bootctl", "").split(",");
return Arrays.asList(modes).contains("memtag");
@@ -43,7 +50,7 @@
}
public static int getAvailabilityStatus() {
- if (MemtagHelper.isForcedOff()) {
+ if (MemtagHelper.isForcedOff() || MemtagHelper.isForcedOn()) {
return BasePreferenceController.DISABLED_DEPENDENT_SETTING;
}
return SystemProperties.getBoolean("ro.arm64.memtag.bootctl_settings_toggle", false)
@@ -65,6 +72,9 @@
if (isForcedOff()) {
return R.string.memtag_force_off;
}
+ if (isForcedOn()) {
+ return R.string.memtag_force_on;
+ }
if (isOn()) {
if (isChecked()) {
return R.string.memtag_on;
diff --git a/src/com/android/settings/spa/app/AllAppList.kt b/src/com/android/settings/spa/app/AllAppList.kt
index 75b5cd2..cd116c1 100644
--- a/src/com/android/settings/spa/app/AllAppList.kt
+++ b/src/com/android/settings/spa/app/AllAppList.kt
@@ -19,6 +19,7 @@
import android.content.pm.ApplicationInfo
import android.os.Bundle
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
import androidx.compose.runtime.remember
import androidx.compose.ui.res.stringResource
import com.android.settings.R
@@ -32,6 +33,8 @@
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spaprivileged.model.app.AppListModel
import com.android.settingslib.spaprivileged.model.app.AppRecord
+import com.android.settingslib.spaprivileged.template.app.AppList
+import com.android.settingslib.spaprivileged.template.app.AppListInput
import com.android.settingslib.spaprivileged.template.app.AppListItem
import com.android.settingslib.spaprivileged.template.app.AppListPage
import com.android.settingslib.spaprivileged.template.app.getStorageSize
@@ -57,17 +60,18 @@
}
@Composable
-private fun AllAppListPage() {
+fun AllAppListPage(
+ appList: @Composable AppListInput<AppRecordWithSize>.() -> Unit = { AppList() },
+) {
val resetAppDialogPresenter = rememberResetAppDialogPresenter()
AppListPage(
title = stringResource(R.string.all_apps),
listModel = remember { AllAppListModel() },
showInstantApps = true,
- moreOptions = { ResetAppPreferences(resetAppDialogPresenter::open) }
+ moreOptions = { ResetAppPreferences(resetAppDialogPresenter::open) },
+ appList = appList,
) {
- AppListItem(
- onClick = AppInfoSettingsProvider.navigator(app = record.app),
- )
+ AppListItem(onClick = AppInfoSettingsProvider.navigator(app = record.app))
}
}
@@ -75,11 +79,13 @@
override val app: ApplicationInfo,
) : AppRecord
-private class AllAppListModel : AppListModel<AppRecordWithSize> {
+class AllAppListModel(
+ private val getSummary: @Composable ApplicationInfo.() -> State<String> = { getStorageSize() },
+) : AppListModel<AppRecordWithSize> {
override fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>) =
appListFlow.mapItem(::AppRecordWithSize)
@Composable
- override fun getSummary(option: Int, record: AppRecordWithSize) = record.app.getStorageSize()
+ override fun getSummary(option: Int, record: AppRecordWithSize) = record.app.getSummary()
}
diff --git a/src/com/android/settings/spa/app/appinfo/AppAllServicesPreference.kt b/src/com/android/settings/spa/app/appinfo/AppAllServicesPreference.kt
index 20e8aca..29c7483 100644
--- a/src/com/android/settings/spa/app/appinfo/AppAllServicesPreference.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppAllServicesPreference.kt
@@ -28,8 +28,9 @@
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
+import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settings.R
-import com.android.settingslib.spa.framework.compose.collectAsStateWithLifecycle
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spaprivileged.model.app.resolveActionForApp
@@ -45,6 +46,7 @@
import kotlinx.coroutines.launch
import kotlinx.coroutines.plus
+@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun AppAllServicesPreference(app: ApplicationInfo) {
val context = LocalContext.current
diff --git a/src/com/android/settings/spa/app/appinfo/AppDataUsagePreference.kt b/src/com/android/settings/spa/app/appinfo/AppDataUsagePreference.kt
index 328f8a5..8b90280 100644
--- a/src/com/android/settings/spa/app/appinfo/AppDataUsagePreference.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppDataUsagePreference.kt
@@ -27,6 +27,8 @@
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
+import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settings.R
import com.android.settings.Utils
import com.android.settings.applications.appinfo.AppInfoDashboardFragment
@@ -34,7 +36,6 @@
import com.android.settings.datausage.DataUsageUtils
import com.android.settingslib.net.NetworkCycleDataForUid
import com.android.settingslib.net.NetworkCycleDataForUidLoader
-import com.android.settingslib.spa.framework.compose.collectAsStateWithLifecycle
import com.android.settingslib.spa.framework.compose.toState
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
@@ -43,6 +44,7 @@
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.withContext
+@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun AppDataUsagePreference(app: ApplicationInfo) {
val context = LocalContext.current
diff --git a/src/com/android/settings/spa/app/appinfo/AppInstallerInfoPreference.kt b/src/com/android/settings/spa/app/appinfo/AppInstallerInfoPreference.kt
index 8d9c98a..b89d768 100644
--- a/src/com/android/settings/spa/app/appinfo/AppInstallerInfoPreference.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppInstallerInfoPreference.kt
@@ -27,7 +27,8 @@
import com.android.settings.Utils
import com.android.settings.applications.AppStoreUtil
import com.android.settingslib.applications.AppUtils
-import com.android.settingslib.spa.framework.compose.collectAsStateWithLifecycle
+import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spaprivileged.framework.common.asUser
@@ -44,6 +45,7 @@
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
+@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun AppInstallerInfoPreference(app: ApplicationInfo) {
val context = LocalContext.current
diff --git a/src/com/android/settings/spa/app/appinfo/AppLocalePreference.kt b/src/com/android/settings/spa/app/appinfo/AppLocalePreference.kt
index b9607b0..e95c5a1 100644
--- a/src/com/android/settings/spa/app/appinfo/AppLocalePreference.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppLocalePreference.kt
@@ -31,7 +31,8 @@
import com.android.settings.applications.AppLocaleUtil
import com.android.settings.applications.appinfo.AppLocaleDetails
import com.android.settings.localepicker.AppLocalePickerActivity
-import com.android.settingslib.spa.framework.compose.collectAsStateWithLifecycle
+import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spaprivileged.model.app.userHandle
@@ -40,6 +41,7 @@
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.withContext
+@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun AppLocalePreference(app: ApplicationInfo) {
val context = LocalContext.current
diff --git a/src/com/android/settings/spa/app/appinfo/AppPermissionSummary.kt b/src/com/android/settings/spa/app/appinfo/AppPermissionSummary.kt
index f73c35a..58edee6 100644
--- a/src/com/android/settings/spa/app/appinfo/AppPermissionSummary.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppPermissionSummary.kt
@@ -37,19 +37,19 @@
private val app: ApplicationInfo,
) : LiveData<AppPermissionSummaryState>() {
private val userContext = context.asUser(app.userHandle)
- private val packageManager = userContext.packageManager
+ private val userPackageManager = userContext.packageManager
private val onPermissionsChangedListener = OnPermissionsChangedListener { uid ->
if (uid == app.uid) update()
}
override fun onActive() {
- packageManager.addOnPermissionsChangeListener(onPermissionsChangedListener)
+ userPackageManager.addOnPermissionsChangeListener(onPermissionsChangedListener)
update()
}
override fun onInactive() {
- packageManager.removeOnPermissionsChangeListener(onPermissionsChangedListener)
+ userPackageManager.removeOnPermissionsChangeListener(onPermissionsChangedListener)
}
private fun update() {
@@ -69,12 +69,10 @@
return
}
val labels = getDisplayLabels(additionalGrantedPermissionCount, grantedGroupLabels)
- val summary = when {
- labels.isEmpty() -> {
- context.getString(R.string.runtime_permissions_summary_no_permissions_granted)
- }
-
- else -> ListFormatter.getInstance().format(labels)
+ val summary = if (labels.isNotEmpty()) {
+ ListFormatter.getInstance().format(labels)
+ } else {
+ context.getString(R.string.runtime_permissions_summary_no_permissions_granted)
}
postValue(AppPermissionSummaryState(summary = summary, enabled = true))
}
diff --git a/src/com/android/settings/spa/app/appinfo/AppSettingsPreference.kt b/src/com/android/settings/spa/app/appinfo/AppSettingsPreference.kt
index ee0212a..d700641 100644
--- a/src/com/android/settings/spa/app/appinfo/AppSettingsPreference.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppSettingsPreference.kt
@@ -28,7 +28,8 @@
import androidx.compose.ui.res.stringResource
import com.android.settings.R
import com.android.settings.overlay.FeatureFactory
-import com.android.settingslib.spa.framework.compose.collectAsStateWithLifecycle
+import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spaprivileged.model.app.resolveActionForApp
@@ -43,6 +44,7 @@
import kotlinx.coroutines.launch
import kotlinx.coroutines.plus
+@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun AppSettingsPreference(app: ApplicationInfo) {
val context = LocalContext.current
diff --git a/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt b/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt
index a38901e..d981067 100644
--- a/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt
+++ b/src/com/android/settings/spa/app/appinfo/HibernationSwitchPreference.kt
@@ -35,7 +35,8 @@
import com.android.settings.Utils.PROPERTY_APP_HIBERNATION_ENABLED
import com.android.settings.Utils.PROPERTY_HIBERNATION_TARGETS_PRE_S_APPS
import com.android.settingslib.spa.framework.compose.OverridableFlow
-import com.android.settingslib.spa.framework.compose.collectAsStateWithLifecycle
+import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settingslib.spa.framework.compose.stateOf
import com.android.settingslib.spa.widget.preference.SwitchPreference
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
@@ -51,6 +52,7 @@
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
+@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun HibernationSwitchPreference(app: ApplicationInfo) {
val context = LocalContext.current
diff --git a/src/com/android/settings/spa/app/appinfo/InstantAppDomainsPreference.kt b/src/com/android/settings/spa/app/appinfo/InstantAppDomainsPreference.kt
index 3a7d50d..0e93b56 100644
--- a/src/com/android/settings/spa/app/appinfo/InstantAppDomainsPreference.kt
+++ b/src/com/android/settings/spa/app/appinfo/InstantAppDomainsPreference.kt
@@ -34,7 +34,8 @@
import androidx.compose.ui.res.stringResource
import com.android.settings.R
import com.android.settings.Utils
-import com.android.settingslib.spa.framework.compose.collectAsStateWithLifecycle
+import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
@@ -45,6 +46,7 @@
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
+@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun InstantAppDomainsPreference(app: ApplicationInfo) {
val context = LocalContext.current
diff --git a/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreference.kt b/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreference.kt
index 15d0501..2430e73 100644
--- a/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreference.kt
+++ b/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreference.kt
@@ -25,7 +25,8 @@
import com.android.settings.R
import com.android.settings.applications.appinfo.AppInfoDashboardFragment
import com.android.settings.applications.specialaccess.interactacrossprofiles.InteractAcrossProfilesDetails
-import com.android.settingslib.spa.framework.compose.collectAsStateWithLifecycle
+import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spaprivileged.framework.common.crossProfileApps
@@ -33,6 +34,7 @@
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
+@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun InteractAcrossProfilesDetailsPreference(app: ApplicationInfo) {
val context = LocalContext.current
diff --git a/src/com/android/settings/spa/system/AppLanguagesListModel.kt b/src/com/android/settings/spa/system/AppLanguagesListModel.kt
index 50b23d3..eea72f2 100644
--- a/src/com/android/settings/spa/system/AppLanguagesListModel.kt
+++ b/src/com/android/settings/spa/system/AppLanguagesListModel.kt
@@ -23,16 +23,13 @@
import androidx.compose.runtime.State
import androidx.compose.runtime.remember
import androidx.compose.ui.res.stringResource
+import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settings.R
import com.android.settings.applications.AppLocaleUtil
import com.android.settings.applications.appinfo.AppLocaleDetails
-import com.android.settingslib.applications.ApplicationsState
-import com.android.settingslib.applications.ApplicationsState.AppEntry
-import com.android.settingslib.spa.framework.compose.collectAsStateWithLifecycle
-import com.android.settingslib.spa.framework.util.asyncMapItem
import com.android.settingslib.spaprivileged.model.app.AppListModel
import com.android.settingslib.spaprivileged.model.app.AppRecord
-import com.android.settingslib.spaprivileged.model.app.userId
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flow
@@ -70,6 +67,7 @@
recordList.filter { it.isAppLocaleSupported }
}
+ @OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
override fun getSummary(option: Int, record: AppLanguagesRecord): State<String>? =
remember(record.app) {
diff --git a/src/com/android/settings/system/ResetDashboardFragment.java b/src/com/android/settings/system/ResetDashboardFragment.java
index c352b92..aea92aa 100644
--- a/src/com/android/settings/system/ResetDashboardFragment.java
+++ b/src/com/android/settings/system/ResetDashboardFragment.java
@@ -24,6 +24,7 @@
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.network.EraseEuiccDataController;
import com.android.settings.network.NetworkResetPreferenceController;
+import com.android.settings.network.SubscriptionUtil;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -61,7 +62,9 @@
@Override
public void onAttach(Context context) {
super.onAttach(context);
- use(EraseEuiccDataController.class).setFragment(this);
+ if (SubscriptionUtil.isSimHardwareVisible(context)) {
+ use(EraseEuiccDataController.class).setFragment(this);
+ }
}
@Override
@@ -72,7 +75,9 @@
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
- controllers.add(new NetworkResetPreferenceController(context));
+ if (SubscriptionUtil.isSimHardwareVisible(context)) {
+ controllers.add(new NetworkResetPreferenceController(context));
+ }
controllers.add(new FactoryResetPreferenceController(context));
controllers.add(new ResetAppPrefPreferenceController(context, lifecycle));
return controllers;
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index d883587..ac2b26b 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -590,6 +590,7 @@
}
private void onAddGuestClicked() {
+ Context context = getContext();
final UserCreatingDialog guestCreatingDialog =
new UserCreatingDialog(getActivity(), /* isGuest= */ true);
guestCreatingDialog.show();
@@ -597,18 +598,18 @@
ThreadUtils.postOnBackgroundThread(() -> {
mMetricsFeatureProvider.action(getActivity(), SettingsEnums.ACTION_USER_GUEST_ADD);
Trace.beginSection("UserSettings.addGuest");
- final UserInfo guest = mUserManager.createGuest(getContext());
+ final UserInfo guest = mUserManager.createGuest(context);
Trace.endSection();
ThreadUtils.postOnMainThread(() -> {
guestCreatingDialog.dismiss();
if (guest == null) {
- Toast.makeText(getContext(),
+ Toast.makeText(context,
com.android.settingslib.R.string.add_guest_failed,
Toast.LENGTH_SHORT).show();
return;
}
- openUserDetails(guest, true);
+ openUserDetails(guest, true, context);
});
});
}
@@ -622,14 +623,10 @@
}
}
- private void onUserCreated(UserInfo userInfo) {
+ private void onUserCreated(UserInfo userInfo, Context context) {
hideUserCreatingDialog();
- // prevent crash when config changes during user creation
- if (getContext() == null) {
- return;
- }
mAddingUser = false;
- openUserDetails(userInfo, true);
+ openUserDetails(userInfo, true, context);
}
private void hideUserCreatingDialog() {
@@ -646,11 +643,21 @@
}
private void openUserDetails(UserInfo userInfo, boolean newUser) {
+ openUserDetails(userInfo, newUser, getContext());
+ }
+
+ private void openUserDetails(UserInfo userInfo, boolean newUser, Context context) {
+ // to prevent a crash when config changes during user creation,
+ // we simply ignore this redirection step
+ if (context == null) {
+ return;
+ }
+
Bundle extras = new Bundle();
extras.putInt(UserDetailsSettings.EXTRA_USER_ID, userInfo.id);
extras.putBoolean(AppRestrictionsFragment.EXTRA_NEW_USER, newUser);
- SubSettingLauncher launcher = new SubSettingLauncher(getContext())
+ SubSettingLauncher launcher = new SubSettingLauncher(context)
.setDestination(UserDetailsSettings.class.getName())
.setArguments(extras)
.setTitleText(userInfo.name)
@@ -1013,6 +1020,9 @@
@VisibleForTesting
void createUser(final int userType, String userName) {
+ Context context = getContext();
+ Resources resources = getResources();
+ final Drawable selectedUserIcon = mPendingUserIcon;
Future<?> unusedCreateUserFuture = ThreadUtils.postOnBackgroundThread(() -> {
UserInfo user;
@@ -1035,19 +1045,19 @@
}
Future<?> unusedSettingIconFuture = ThreadUtils.postOnBackgroundThread(() -> {
- Drawable newUserIcon = mPendingUserIcon;
+ Drawable newUserIcon = selectedUserIcon;
if (newUserIcon == null) {
- newUserIcon = UserIcons.getDefaultUserIcon(getResources(), user.id, false);
+ newUserIcon = UserIcons.getDefaultUserIcon(resources, user.id, false);
}
mUserManager.setUserIcon(
user.id, UserIcons.convertToBitmapAtUserIconSize(
- getResources(), newUserIcon));
+ resources, newUserIcon));
});
mPendingUserIcon = null;
mPendingUserName = null;
- onUserCreated(user);
+ onUserCreated(user, context);
});
});
}
@@ -1582,6 +1592,7 @@
openUserDetails(userInfo, false);
return true;
} else if (pref == mAddUser) {
+ mMetricsFeatureProvider.action(getActivity(), SettingsEnums.ACTION_USER_ADD);
// If we allow both types, show a picker, otherwise directly go to
// flow for full user.
if (mUserCaps.mCanAddRestrictedProfile) {
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
index 5fe156c..5639047 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
@@ -16,7 +16,7 @@
package com.android.settings.wifi;
-import static com.android.settings.wifi.WifiUtils.getWifiEntrySecurity;
+import static com.android.wifitrackerlib.Utils.getSecurityTypesFromScanResult;
import static java.util.stream.Collectors.toList;
@@ -77,8 +77,12 @@
private static final int MAX_NUMBER_LIST_ITEM = 5;
private boolean mShowLimitedItem = true;
+ private static class MatchWifi {
+ String mSsid;
+ List<Integer> mSecurityTypes;
+ }
+ private List<MatchWifi> mMatchWifis = new ArrayList<>();
@VisibleForTesting List<WifiEntry> mFilteredWifiEntries = new ArrayList<>();
- @VisibleForTesting List<ScanResult> mMatchedScanResults = new ArrayList<>();
private WifiEntryAdapter mDialogAdapter;
private NetworkRequestUserSelectionCallback mUserSelectionCallback;
@@ -237,7 +241,7 @@
/** Called when the state of Wifi has changed. */
@Override
public void onWifiStateChanged() {
- if (mMatchedScanResults.size() == 0) {
+ if (mMatchWifis.size() == 0) {
return;
}
updateWifiEntries();
@@ -249,7 +253,7 @@
*/
@Override
public void onWifiEntriesChanged() {
- if (mMatchedScanResults.size() == 0) {
+ if (mMatchWifis.size() == 0) {
return;
}
updateWifiEntries();
@@ -275,16 +279,24 @@
wifiEntries.addAll(mWifiPickerTracker.getWifiEntries());
mFilteredWifiEntries.clear();
- mFilteredWifiEntries.addAll(wifiEntries.stream().filter(entry -> {
- for (ScanResult matchedScanResult : mMatchedScanResults) {
- if (TextUtils.equals(entry.getSsid(), matchedScanResult.SSID)
- && entry.getSecurity() == getWifiEntrySecurity(matchedScanResult)) {
+ mFilteredWifiEntries.addAll(wifiEntries.stream()
+ .filter(entry -> isMatchedWifiEntry(entry))
+ .limit(mShowLimitedItem ? MAX_NUMBER_LIST_ITEM : Long.MAX_VALUE)
+ .collect(toList()));
+ }
+
+ private boolean isMatchedWifiEntry(WifiEntry entry) {
+ for (MatchWifi wifi : mMatchWifis) {
+ if (!TextUtils.equals(entry.getSsid(), wifi.mSsid)) {
+ continue;
+ }
+ for (Integer security : wifi.mSecurityTypes) {
+ if (entry.getSecurityTypes().contains(security)) {
return true;
}
}
- return false;
- }).limit(mShowLimitedItem ? MAX_NUMBER_LIST_ITEM : Long.MAX_VALUE)
- .collect(toList()));
+ }
+ return false;
}
private class WifiEntryAdapter extends ArrayAdapter<WifiEntry> {
@@ -350,7 +362,14 @@
@Override
public void onMatch(List<ScanResult> scanResults) {
- mMatchedScanResults = scanResults;
+ mMatchWifis.clear();
+ for (ScanResult scanResult : scanResults) {
+ MatchWifi matchWifi = new MatchWifi();
+ matchWifi.mSsid = scanResult.SSID;
+ matchWifi.mSecurityTypes = getSecurityTypesFromScanResult(scanResult);
+ mMatchWifis.add(matchWifi);
+ }
+
updateWifiEntries();
updateUi();
}
diff --git a/tests/robotests/assets/exempt_not_implementing_index_provider b/tests/robotests/assets/exempt_not_implementing_index_provider
index 6a1a1ff..7099089 100644
--- a/tests/robotests/assets/exempt_not_implementing_index_provider
+++ b/tests/robotests/assets/exempt_not_implementing_index_provider
@@ -92,4 +92,3 @@
com.android.settings.applications.specialaccess.notificationaccess.NotificationAccessDetails
com.android.settings.wifi.details2.WifiNetworkDetailsFragment2
com.android.settings.wifi.savedaccesspoints2.SavedAccessPointsWifiSettings2
-com.android.settings.dashboard.profileselector.ProfileSelectRecentLocationRequestFragment
diff --git a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreviewPreferenceTest.java b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreviewPreferenceTest.java
index 3dc82da..1688142 100644
--- a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreviewPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreviewPreferenceTest.java
@@ -129,6 +129,17 @@
verify(mPreviewPagerAdapter).setPreviewLayer(eq(index), anyInt(), anyInt(), anyBoolean());
}
+ @Test
+ public void afterPagerChange_updateCurrentItem() {
+ final int currentItem = 2;
+ mTextReadingPreviewPreference.setPreviewAdapter(mPreviewPagerAdapter);
+ mTextReadingPreviewPreference.onBindViewHolder(mHolder);
+
+ mViewPager.setCurrentItem(currentItem);
+
+ assertThat(mTextReadingPreviewPreference.getCurrentItem()).isEqualTo(currentItem);
+ }
+
private static Configuration[] createConfigurations(int count) {
final Configuration[] configurations = new Configuration[count];
for (int i = 0; i < count; i++) {
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusDevicesControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusDevicesControllerTest.java
index f704f2d..b1ca911 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusDevicesControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusDevicesControllerTest.java
@@ -32,6 +32,7 @@
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.provider.Settings;
+import android.provider.Settings.Secure;
import android.view.InputDevice;
import android.view.inputmethod.InputMethodManager;
@@ -227,6 +228,42 @@
Settings.Global.STYLUS_HANDWRITING_ENABLED, -1)).isEqualTo(1);
}
+ @Test
+ public void buttonsPreference_checkedWhenFlagTrue() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.STYLUS_BUTTONS_DISABLED, 1);
+
+ showScreen(mController);
+ SwitchPreference buttonsPref = (SwitchPreference) mPreferenceContainer.getPreference(2);
+
+ assertThat(buttonsPref.isChecked()).isEqualTo(true);
+ }
+
+ @Test
+ public void buttonsPreference_uncheckedWhenFlagFalse() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.STYLUS_BUTTONS_DISABLED, 0);
+
+ showScreen(mController);
+ SwitchPreference buttonsPref = (SwitchPreference) mPreferenceContainer.getPreference(2);
+
+ assertThat(buttonsPref.isChecked()).isEqualTo(false);
+ }
+
+ @Test
+ public void buttonsPreference_updatesFlagOnClick() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.STYLUS_BUTTONS_DISABLED, 1);
+ showScreen(mController);
+ SwitchPreference buttonsPref = (SwitchPreference) mPreferenceContainer.getPreference(2);
+
+ buttonsPref.performClick();
+
+ assertThat(buttonsPref.isChecked()).isEqualTo(false);
+ assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
+ Secure.STYLUS_BUTTONS_DISABLED, -1)).isEqualTo(0);
+ }
+
private void showScreen(StylusDevicesController controller) {
controller.displayPreference(mScreen);
}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerTest.java
index 0ca5fd2..9d4956d 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerTest.java
@@ -72,6 +72,7 @@
private Context mContext;
private Resources mResources;
+ private SlotSimStatus mSlotSimStatus;
private SimStatusPreferenceController mController;
@Before
@@ -105,13 +106,13 @@
final String prefKey = mController.getPreferenceKey();
when(mPreference.getKey()).thenReturn(prefKey);
when(mPreference.isVisible()).thenReturn(true);
-
- mController.init(mFragment, SubscriptionManager.INVALID_SIM_SLOT_INDEX);
}
@Test
public void displayPreference_multiSim_shouldAddSecondPreference() {
when(mTelephonyManager.getPhoneCount()).thenReturn(2);
+ SlotSimStatus slotSimStatus = new SlotSimStatus(mContext);
+ mController.init(mFragment, slotSimStatus);
mController.displayPreference(mScreen);
@@ -121,6 +122,8 @@
@Test
public void updateState_singleSim_shouldSetSingleSimTitleAndSummary() {
when(mTelephonyManager.getPhoneCount()).thenReturn(1);
+ SlotSimStatus slotSimStatus = new SlotSimStatus(mContext);
+ mController.init(mFragment, slotSimStatus);
mController.displayPreference(mScreen);
mController.updateState(mPreference);
@@ -132,6 +135,8 @@
@Test
public void updateState_multiSim_shouldSetMultiSimTitleAndSummary() {
when(mTelephonyManager.getPhoneCount()).thenReturn(2);
+ SlotSimStatus slotSimStatus = new SlotSimStatus(mContext);
+ mController.init(mFragment, slotSimStatus);
mController.displayPreference(mScreen);
mController.updateState(mPreference);
@@ -149,6 +154,8 @@
when(mFragment.getChildFragmentManager()).thenReturn(
mock(FragmentManager.class, Answers.RETURNS_DEEP_STUBS));
when(mTelephonyManager.getPhoneCount()).thenReturn(2);
+ SlotSimStatus slotSimStatus = new SlotSimStatus(mContext);
+ mController.init(mFragment, slotSimStatus);
mController.displayPreference(mScreen);
mController.handlePreferenceTreeClick(mFirstSimPreference);
diff --git a/tests/robotests/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceControllerTest.java
index 8597d64..4ad5c22 100644
--- a/tests/robotests/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/CustomizableLockScreenQuickAffordancesPreferenceControllerTest.java
@@ -102,6 +102,8 @@
assertThat(intentCaptor.getValue().getPackage()).isEqualTo(
mContext.getString(R.string.config_wallpaper_picker_package));
assertThat(intentCaptor.getValue().getAction()).isEqualTo(Intent.ACTION_SET_WALLPAPER);
+ assertThat(intentCaptor.getValue().getStringExtra("destination"))
+ .isEqualTo("quick_affordances");
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java
index 284dbe3..15b7e02 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java
@@ -68,6 +68,7 @@
private static final String STATUS_CHARGING_TIME = "50% - 0 min left until full";
private static final String STATUS_NOT_CHARGING = "Not charging";
private static final String STATUS_CHARGING_FUTURE_BYPASS = "50% - Charging to 12%";
+ private static final String STATUS_CHARGING_PAUSED = "50% - Charging paused";
private static final long REMAINING_TIME_NULL = -1;
private static final long REMAINING_TIME = 2;
// Strings are defined in frameworks/base/packages/SettingsLib/res/values/strings.xml
@@ -256,8 +257,6 @@
@Test
public void testGetBatteryInfo_chargingWithOverheated_updateChargeLabel() {
- final String expectedString =
- mContext.getString(R.string.battery_tip_limited_temporarily_title);
doReturn(TEST_CHARGE_TIME_REMAINING)
.when(mBatteryUsageStats)
.getChargeTimeRemainingMs();
@@ -269,13 +268,11 @@
false /* shortString */);
assertThat(info.isOverheated).isTrue();
- assertThat(info.chargeLabel.toString()).contains(expectedString);
+ assertThat(info.chargeLabel.toString()).contains(STATUS_CHARGING_PAUSED);
}
@Test
public void testGetBatteryInfo_dockDefenderActive_updateChargeString() {
- final String expectedString =
- mContext.getString(R.string.battery_tip_limited_temporarily_title);
doReturn(TEST_CHARGE_TIME_REMAINING / 1000)
.when(mBatteryUsageStats).getChargeTimeRemainingMs();
doReturn(true).when(mFeatureFactory.powerUsageFeatureProvider).isExtraDefend();
@@ -289,7 +286,7 @@
mBatteryUsageStats, MOCK_ESTIMATE, SystemClock.elapsedRealtime() * 1000,
false /* shortString */);
- assertThat(info.chargeLabel.toString()).contains(expectedString);
+ assertThat(info.chargeLabel.toString()).contains(STATUS_CHARGING_PAUSED);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTipTest.java
index d917d89..69d5477 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/DockDefenderTipTest.java
@@ -109,12 +109,22 @@
}
@Test
- public void testGetIconId() {
- assertThat(mDockDefenderTipFutureBypass.getIconId()).isEqualTo(
+ public void testGetIconId_dockDefenderActive_getProtectedIcon() {
+ assertThat(mDockDefenderTipActive.getIconId()).isEqualTo(
R.drawable.ic_battery_status_protected_24dp);
}
@Test
+ public void testGetIconId_dockDefenderNotActive_getUntriggeredIcon() {
+ assertThat(mDockDefenderTipFutureBypass.getIconId()).isEqualTo(
+ R.drawable.ic_battery_dock_defender_untriggered_24dp);
+ assertThat(mDockDefenderTipTemporarilyBypassed.getIconId()).isEqualTo(
+ R.drawable.ic_battery_dock_defender_untriggered_24dp);
+ assertThat(mDockDefenderTipDisabled.getIconId()).isEqualTo(
+ R.drawable.ic_battery_dock_defender_untriggered_24dp);
+ }
+
+ @Test
public void testUpdateState() {
mDockDefenderTipTemporarilyBypassed.updateState(mDockDefenderTipDisabled);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
index 5c84997..95e3bad 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
@@ -19,21 +19,22 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
-import android.app.settings.SettingsEnums;
import android.content.ContentValues;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
+import android.os.BatteryManager;
import android.os.Bundle;
import android.os.LocaleList;
import android.text.format.DateUtils;
@@ -41,27 +42,17 @@
import android.view.ViewPropertyAnimator;
import android.widget.LinearLayout;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceGroup;
-
import com.android.settings.SettingsActivity;
-import com.android.settings.core.InstrumentedPreferenceFragment;
-import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@@ -70,18 +61,11 @@
@RunWith(RobolectricTestRunner.class)
public final class BatteryChartPreferenceControllerTest {
- private static final String PREF_KEY = "pref_key";
- private static final String PREF_SUMMARY = "fake preference summary";
-
@Mock
- private InstrumentedPreferenceFragment mFragment;
+ private Intent mIntent;
@Mock
private SettingsActivity mSettingsActivity;
@Mock
- private PreferenceGroup mAppListGroup;
- @Mock
- private Drawable mDrawable;
- @Mock
private BatteryHistEntry mBatteryHistEntry;
@Mock
private BatteryChartView mDailyChartView;
@@ -90,16 +74,11 @@
@Mock
private ViewPropertyAnimator mViewPropertyAnimator;
@Mock
- private PowerGaugePreference mPowerGaugePreference;
- @Mock
- private BatteryUtils mBatteryUtils;
- @Mock
private LinearLayout.LayoutParams mLayoutParams;
private Context mContext;
private FakeFeatureFactory mFeatureFactory;
private BatteryDiffEntry mBatteryDiffEntry;
- private MetricsFeatureProvider mMetricsFeatureProvider;
private BatteryChartPreferenceController mBatteryChartPreferenceController;
@Before
@@ -109,7 +88,6 @@
org.robolectric.shadows.ShadowSettings.set24HourTimeFormat(false);
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
mFeatureFactory = FakeFeatureFactory.setupForTest();
- mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
mContext = spy(RuntimeEnvironment.application);
final Resources resources = spy(mContext.getResources());
resources.getConfiguration().setLocales(new LocaleList(new Locale("en_US")));
@@ -118,16 +96,17 @@
.when(mFeatureFactory.powerUsageFeatureProvider)
.getHideApplicationEntries(mContext);
doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
+ doReturn(mIntent).when(mContext).registerReceiver(any(), any());
+ doReturn(100).when(mIntent).getIntExtra(eq(BatteryManager.EXTRA_SCALE), anyInt());
+ doReturn(66).when(mIntent).getIntExtra(eq(BatteryManager.EXTRA_LEVEL), anyInt());
setupHourlyChartViewAnimationMock();
mBatteryChartPreferenceController = createController();
mBatteryChartPreferenceController.mPrefContext = mContext;
- mBatteryChartPreferenceController.mAppListPrefGroup = mAppListGroup;
mBatteryChartPreferenceController.mDailyChartView = mDailyChartView;
mBatteryChartPreferenceController.mHourlyChartView = mHourlyChartView;
mBatteryDiffEntry = new BatteryDiffEntry(
mContext,
/*foregroundUsageTimeInMs=*/ 1,
- /*foregroundServiceUsageTimeInMs=*/ 3,
/*backgroundUsageTimeInMs=*/ 2,
/*consumePower=*/ 3,
/*foregroundUsageConsumePower=*/ 0,
@@ -163,24 +142,6 @@
}
@Test
- public void onDestroy_clearPreferenceCache() {
- // Ensures the testing environment is correct.
- mBatteryChartPreferenceController.mPreferenceCache.put(
- PREF_KEY, mPowerGaugePreference);
- assertThat(mBatteryChartPreferenceController.mPreferenceCache).hasSize(1);
-
- mBatteryChartPreferenceController.onDestroy();
- // Verifies the result after onDestroy.
- assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
- }
-
- @Test
- public void onDestroy_removeAllPreferenceFromPreferenceGroup() {
- mBatteryChartPreferenceController.onDestroy();
- verify(mAppListGroup).removeAll();
- }
-
- @Test
public void setBatteryChartViewModel_6Hours() {
reset(mDailyChartView);
reset(mHourlyChartView);
@@ -192,10 +153,11 @@
// Ignore fast refresh ui from the data processor callback.
verify(mHourlyChartView, atLeast(0)).setViewModel(null);
verify(mHourlyChartView, atLeastOnce()).setViewModel(new BatteryChartViewModel(
- List.of(100, 97, 95),
+ List.of(100, 97, 95, 66),
List.of(1619251200000L /* 8 AM */,
1619258400000L /* 10 AM */,
- 1619265600000L /* 12 PM */),
+ 1619265600000L /* 12 PM */,
+ 1619272800000L /* 2 PM */),
BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS,
mBatteryChartPreferenceController.mHourlyChartLabelTextGenerator));
}
@@ -207,12 +169,12 @@
setupHourlyChartViewAnimationMock();
BatteryChartViewModel expectedDailyViewModel = new BatteryChartViewModel(
- List.of(100, 83, 59, 41),
+ List.of(100, 83, 59, 66),
// "Sat", "Sun", "Mon", "Mon"
List.of(1619251200000L /* Sat */,
1619308800000L /* Sun */,
1619395200000L /* Mon */,
- 1619460000000L /* Mon */),
+ 1619467200000L /* Mon */),
BatteryChartViewModel.AxisLabelPosition.CENTER_OF_TRAPEZOIDS,
mBatteryChartPreferenceController.mDailyChartLabelTextGenerator);
@@ -292,7 +254,7 @@
expectedDailyViewModel.setSelectedIndex(2);
verify(mDailyChartView).setViewModel(expectedDailyViewModel);
verify(mHourlyChartView).setViewModel(new BatteryChartViewModel(
- List.of(59, 57, 55, 53, 51, 49, 47, 45, 43, 41),
+ List.of(59, 57, 55, 53, 51, 49, 47, 45, 43, 41, 66),
List.of(1619395200000L /* 12 AM */,
1619402400000L /* 2 AM */,
1619409600000L /* 4 AM */,
@@ -302,9 +264,11 @@
1619438400000L /* 12 PM */,
1619445600000L /* 2 PM */,
1619452800000L /* 4 PM */,
- 1619460000000L /* 6 PM */),
+ 1619460000000L /* 6 PM */,
+ 1619467200000L /* 8 PM */),
BatteryChartViewModel.AxisLabelPosition.BETWEEN_TRAPEZOIDS,
mBatteryChartPreferenceController.mHourlyChartLabelTextGenerator));
+
}
@Test
@@ -314,9 +278,9 @@
}
@Test
- public void refreshUi_batteryIndexedMapIsNull_ignoreRefresh() {
+ public void refreshUi_batteryIndexedMapIsNull_returnTrue() {
mBatteryChartPreferenceController.setBatteryHistoryMap(null);
- assertThat(mBatteryChartPreferenceController.refreshUi()).isFalse();
+ assertThat(mBatteryChartPreferenceController.refreshUi()).isTrue();
}
@Test
@@ -332,266 +296,6 @@
}
@Test
- public void removeAndCacheAllPrefs_emptyContent_ignoreRemoveAll() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
- mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
- doReturn(0).when(mAppListGroup).getPreferenceCount();
-
- mBatteryChartPreferenceController.refreshUi();
- verify(mAppListGroup, never()).removeAll();
- }
-
- @Test
- public void removeAndCacheAllPrefs_buildCacheAndRemoveAllPreference() {
- mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
- mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
- doReturn(1).when(mAppListGroup).getPreferenceCount();
- doReturn(mPowerGaugePreference).when(mAppListGroup).getPreference(0);
- doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
- doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
- doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
- // Ensures the testing data is correct.
- assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
-
- mBatteryChartPreferenceController.refreshUi();
-
- assertThat(mBatteryChartPreferenceController.mPreferenceCache.get(PREF_KEY))
- .isEqualTo(mPowerGaugePreference);
- verify(mAppListGroup).removeAll();
- }
-
- @Test
- public void addPreferenceToScreen_emptyContent_ignoreAddPreference() {
- mBatteryChartPreferenceController.addPreferenceToScreen(
- new ArrayList<BatteryDiffEntry>());
- verify(mAppListGroup, never()).addPreference(any());
- }
-
- @Test
- public void addPreferenceToScreen_addPreferenceIntoScreen() {
- final String appLabel = "fake app label";
- doReturn(1).when(mAppListGroup).getPreferenceCount();
- doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
- doReturn(appLabel).when(mBatteryDiffEntry).getAppLabel();
- doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
- doReturn(null).when(mAppListGroup).findPreference(PREF_KEY);
- doReturn(false).when(mBatteryDiffEntry).validForRestriction();
-
- mBatteryChartPreferenceController.addPreferenceToScreen(
- Arrays.asList(mBatteryDiffEntry));
-
- // Verifies the preference cache.
- final PowerGaugePreference pref =
- (PowerGaugePreference) mBatteryChartPreferenceController.mPreferenceCache
- .get(PREF_KEY);
- assertThat(pref).isNotNull();
- // Verifies the added preference configuration.
- verify(mAppListGroup).addPreference(pref);
- assertThat(pref.getKey()).isEqualTo(PREF_KEY);
- assertThat(pref.getTitle()).isEqualTo(appLabel);
- assertThat(pref.getIcon()).isEqualTo(mDrawable);
- assertThat(pref.getOrder()).isEqualTo(1);
- assertThat(pref.getBatteryDiffEntry()).isSameInstanceAs(mBatteryDiffEntry);
- assertThat(pref.isSingleLineTitle()).isTrue();
- assertThat(pref.isEnabled()).isFalse();
- }
-
- @Test
- public void addPreferenceToScreen_alreadyInScreen_notAddPreferenceAgain() {
- final String appLabel = "fake app label";
- doReturn(1).when(mAppListGroup).getPreferenceCount();
- doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
- doReturn(appLabel).when(mBatteryDiffEntry).getAppLabel();
- doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
- doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
-
- mBatteryChartPreferenceController.addPreferenceToScreen(
- Arrays.asList(mBatteryDiffEntry));
-
- verify(mAppListGroup, never()).addPreference(any());
- }
-
- @Test
- public void handlePreferenceTreeClick_notPowerGaugePreference_returnFalse() {
- assertThat(mBatteryChartPreferenceController.handlePreferenceTreeClick(mAppListGroup))
- .isFalse();
-
- verify(mMetricsFeatureProvider, never())
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_APP_ITEM);
- verify(mMetricsFeatureProvider, never())
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SYSTEM_ITEM);
- }
-
- @Test
- public void handlePreferenceTreeClick_forAppEntry_returnTrue() {
- doReturn(false).when(mBatteryHistEntry).isAppEntry();
- doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
-
- assertThat(mBatteryChartPreferenceController.handlePreferenceTreeClick(
- mPowerGaugePreference)).isTrue();
- verify(mMetricsFeatureProvider)
- .action(
- SettingsEnums.OPEN_BATTERY_USAGE,
- SettingsEnums.ACTION_BATTERY_USAGE_SYSTEM_ITEM,
- SettingsEnums.OPEN_BATTERY_USAGE,
- /* package name */ "none",
- /* percentage of total */ 0);
- }
-
- @Test
- public void handlePreferenceTreeClick_forSystemEntry_returnTrue() {
- mBatteryChartPreferenceController.mBatteryUtils = mBatteryUtils;
- doReturn(true).when(mBatteryHistEntry).isAppEntry();
- doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
-
- assertThat(mBatteryChartPreferenceController.handlePreferenceTreeClick(
- mPowerGaugePreference)).isTrue();
- verify(mMetricsFeatureProvider)
- .action(
- SettingsEnums.OPEN_BATTERY_USAGE,
- SettingsEnums.ACTION_BATTERY_USAGE_APP_ITEM,
- SettingsEnums.OPEN_BATTERY_USAGE,
- /* package name */ "none",
- /* percentage of total */ 0);
- }
-
- @Test
- public void setPreferenceSummary_setNullContentIfTotalUsageTimeIsZero() {
- final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary(PREF_SUMMARY);
-
- mBatteryChartPreferenceController.setPreferenceSummary(
- pref, createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ 0,
- /*foregroundServiceUsageTimeInMs=*/ 0,
- /*backgroundUsageTimeInMs=*/ 0));
- assertThat(pref.getSummary()).isNull();
- }
-
- @Test
- public void setPreferenceSummary_setBackgroundUsageTimeOnly() {
- final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary(PREF_SUMMARY);
-
- mBatteryChartPreferenceController.setPreferenceSummary(
- pref, createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ 0,
- /*foregroundServiceUsageTimeInMs=*/ 0,
- /*backgroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS));
- assertThat(pref.getSummary()).isEqualTo("Background: 1 min");
- }
-
- @Test
- public void setPreferenceSummary_setTotalUsageTimeLessThanAMinute() {
- final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary(PREF_SUMMARY);
-
- mBatteryChartPreferenceController.setPreferenceSummary(
- pref, createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ 100,
- /*foregroundServiceUsageTimeInMs=*/ 200,
- /*backgroundUsageTimeInMs=*/ 200));
- assertThat(pref.getSummary()).isEqualTo("Total: less than a min");
- }
-
- @Test
- public void setPreferenceSummary_setTotalTimeIfBackgroundTimeLessThanAMinute() {
- final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary(PREF_SUMMARY);
-
- mBatteryChartPreferenceController.setPreferenceSummary(
- pref, createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
- /*foregroundServiceUsageTimeInMs=*/ 100,
- /*backgroundUsageTimeInMs=*/ 200));
- assertThat(pref.getSummary())
- .isEqualTo("Total: 1 min\nBackground: less than a min");
- }
-
- @Test
- public void setPreferenceSummary_setTotalAndBackgroundUsageTime() {
- final PowerGaugePreference pref = new PowerGaugePreference(mContext);
- pref.setSummary(PREF_SUMMARY);
-
- mBatteryChartPreferenceController.setPreferenceSummary(
- pref, createBatteryDiffEntry(
- /*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
- /*foregroundServiceUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
- /*backgroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS));
- assertThat(pref.getSummary()).isEqualTo("Total: 2 min\nBackground: 1 min");
- }
-
- @Test
- public void onExpand_expandedIsTrue_addSystemEntriesToPreferenceGroup() {
- doReturn(1).when(mAppListGroup).getPreferenceCount();
- mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
- doReturn("label").when(mBatteryDiffEntry).getAppLabel();
- doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
- doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
-
- mBatteryChartPreferenceController.onExpand(/*isExpanded=*/ true);
-
- final ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
- verify(mAppListGroup).addPreference(captor.capture());
- // Verifies the added preference.
- assertThat(captor.getValue().getKey()).isEqualTo(PREF_KEY);
- verify(mMetricsFeatureProvider)
- .action(
- mContext,
- SettingsEnums.ACTION_BATTERY_USAGE_EXPAND_ITEM,
- true /*isExpanded*/);
- }
-
- @Test
- public void onExpand_expandedIsFalse_removeSystemEntriesFromPreferenceGroup() {
- doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
- doReturn(mPowerGaugePreference).when(mAppListGroup).findPreference(PREF_KEY);
- mBatteryChartPreferenceController.mBatteryUsageMap = createBatteryUsageMap();
- // Verifies the cache is empty first.
- assertThat(mBatteryChartPreferenceController.mPreferenceCache).isEmpty();
-
- mBatteryChartPreferenceController.onExpand(/*isExpanded=*/ false);
-
- verify(mAppListGroup).findPreference(PREF_KEY);
- verify(mAppListGroup).removePreference(mPowerGaugePreference);
- assertThat(mBatteryChartPreferenceController.mPreferenceCache).hasSize(1);
- verify(mMetricsFeatureProvider)
- .action(
- mContext,
- SettingsEnums.ACTION_BATTERY_USAGE_EXPAND_ITEM,
- false /*isExpanded*/);
- }
-
- @Test
- public void refreshCategoryTitle_setLastFullChargeIntoBothTitleTextView() {
- mBatteryChartPreferenceController = createController();
- mBatteryChartPreferenceController.mAppListPrefGroup =
- spy(new PreferenceCategory(mContext));
- mBatteryChartPreferenceController.mExpandDividerPreference =
- spy(new ExpandDividerPreference(mContext));
- // Simulates select all condition.
- mBatteryChartPreferenceController.mDailyChartIndex =
- BatteryChartViewModel.SELECTED_INDEX_ALL;
- mBatteryChartPreferenceController.mHourlyChartIndex =
- BatteryChartViewModel.SELECTED_INDEX_ALL;
-
- mBatteryChartPreferenceController.refreshCategoryTitle();
-
- ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
- // Verifies the title in the preference group.
- verify(mBatteryChartPreferenceController.mAppListPrefGroup)
- .setTitle(captor.capture());
- assertThat(captor.getValue())
- .isEqualTo("App usage since last full charge");
- // Verifies the title in the expandable divider.
- captor = ArgumentCaptor.forClass(String.class);
- verify(mBatteryChartPreferenceController.mExpandDividerPreference)
- .setTitle(captor.capture());
- assertThat(captor.getValue())
- .isEqualTo("System usage since last full charge");
- }
-
- @Test
public void selectedSlotText_selectAllDaysAllHours_returnNull() {
mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
mBatteryChartPreferenceController.mDailyChartIndex =
@@ -646,16 +350,13 @@
public void onSaveInstanceState_restoreSelectedIndexAndExpandState() {
final int expectedDailyIndex = 1;
final int expectedHourlyIndex = 2;
- final boolean isExpanded = true;
final Bundle bundle = new Bundle();
mBatteryChartPreferenceController.mDailyChartIndex = expectedDailyIndex;
mBatteryChartPreferenceController.mHourlyChartIndex = expectedHourlyIndex;
- mBatteryChartPreferenceController.mIsExpanded = isExpanded;
mBatteryChartPreferenceController.onSaveInstanceState(bundle);
// Replaces the original controller with other values.
mBatteryChartPreferenceController.mDailyChartIndex = -1;
mBatteryChartPreferenceController.mHourlyChartIndex = -1;
- mBatteryChartPreferenceController.mIsExpanded = false;
mBatteryChartPreferenceController.onCreate(bundle);
mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(25));
@@ -664,7 +365,6 @@
.isEqualTo(expectedDailyIndex);
assertThat(mBatteryChartPreferenceController.mHourlyChartIndex)
.isEqualTo(expectedHourlyIndex);
- assertThat(mBatteryChartPreferenceController.mIsExpanded).isTrue();
}
@Test
@@ -676,7 +376,7 @@
final int totalHour = BatteryChartPreferenceController.getTotalHours(batteryLevelData);
// Only calculate the even hours.
- assertThat(totalHour).isEqualTo(58);
+ assertThat(totalHour).isEqualTo(60);
}
private static Long generateTimestamp(int index) {
@@ -707,40 +407,15 @@
entryMap.put("fake_entry_key" + index, entry);
batteryHistoryMap.put(generateTimestamp(index), entryMap);
}
+ DataProcessor.sFakeCurrentTimeMillis =
+ generateTimestamp(numOfHours - 1) + DateUtils.MINUTE_IN_MILLIS;
return batteryHistoryMap;
}
- private Map<Integer, Map<Integer, BatteryDiffData>> createBatteryUsageMap() {
- final int selectedAll = BatteryChartViewModel.SELECTED_INDEX_ALL;
- return Map.of(
- selectedAll, Map.of(
- selectedAll, new BatteryDiffData(
- Arrays.asList(mBatteryDiffEntry),
- Arrays.asList(mBatteryDiffEntry))),
- 0, Map.of(
- selectedAll, new BatteryDiffData(
- Arrays.asList(mBatteryDiffEntry),
- Arrays.asList(mBatteryDiffEntry)),
- 0, new BatteryDiffData(
- Arrays.asList(mBatteryDiffEntry),
- Arrays.asList(mBatteryDiffEntry))));
- }
-
- private BatteryDiffEntry createBatteryDiffEntry(
- long foregroundUsageTimeInMs, long foregroundServiceUsageTimeInMs,
- long backgroundUsageTimeInMs) {
- return new BatteryDiffEntry(
- mContext, foregroundUsageTimeInMs, foregroundServiceUsageTimeInMs,
- backgroundUsageTimeInMs, /*consumePower=*/ 0, /*foregroundUsageConsumePower=*/ 0,
- /*foregroundServiceUsageConsumePower=*/ 0, /*backgroundUsageConsumePower=*/ 0,
- /*cachedUsageConsumePower=*/ 0, mBatteryHistEntry);
- }
-
private BatteryChartPreferenceController createController() {
final BatteryChartPreferenceController controller =
new BatteryChartPreferenceController(
- mContext, "app_list", /*lifecycle=*/ null,
- mSettingsActivity, mFragment);
+ mContext, /*lifecycle=*/ null, mSettingsActivity);
controller.mPrefContext = mContext;
return controller;
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
index 0090436..f8bcbc8 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryDiffEntryTest.java
@@ -96,7 +96,6 @@
new BatteryDiffEntry(
mContext,
/*foregroundUsageTimeInMs=*/ 10001L,
- /*foregroundServiceUsageTimeInMs=*/ 10002L,
/*backgroundUsageTimeInMs=*/ 20002L,
/*consumePower=*/ 22.0,
/*foregroundUsageConsumePower=*/ 10.0,
@@ -115,7 +114,6 @@
new BatteryDiffEntry(
mContext,
/*foregroundUsageTimeInMs=*/ 10001L,
- /*foregroundServiceUsageTimeInMs=*/ 10002L,
/*backgroundUsageTimeInMs=*/ 20002L,
/*consumePower=*/ 22.0,
/*foregroundUsageConsumePower=*/ 10.0,
@@ -493,7 +491,6 @@
return new BatteryDiffEntry(
mContext,
/*foregroundUsageTimeInMs=*/ 0,
- /*foregroundServiceUsageTimeInMs=*/ 0,
/*backgroundUsageTimeInMs=*/ 0,
/*consumePower=*/ 0,
/*foregroundUsageConsumePower=*/ 0,
@@ -508,7 +505,6 @@
final BatteryDiffEntry entry = new BatteryDiffEntry(
mContext,
/*foregroundUsageTimeInMs=*/ 0,
- /*foregroundServiceUsageTimeInMs=*/ 0,
/*backgroundUsageTimeInMs=*/ 0,
consumePower,
/*foregroundUsageConsumePower=*/ 0,
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryEntryTest.java
index 90fa572..463a66d 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryEntryTest.java
@@ -104,11 +104,19 @@
}
private BatteryEntry createAggregateBatteryEntry(int powerComponentId) {
- return new BatteryEntry(mMockContext, powerComponentId, 200, 100, 1000);
+ return new BatteryEntry(
+ mMockContext,
+ powerComponentId,
+ /* devicePowerMah= */ 200,
+ /* usageDurationMs= */ 1000);
}
private BatteryEntry createCustomAggregateBatteryEntry(int powerComponentId) {
- return new BatteryEntry(mMockContext, powerComponentId, "CUSTOM", 200, 100);
+ return new BatteryEntry(
+ mMockContext,
+ powerComponentId,
+ /* powerComponentName= */ "CUSTOM",
+ /* devicePowerMah= */ 200);
}
private BatteryEntry createUserBatteryConsumer(int userId) {
@@ -159,7 +167,9 @@
@Test
public void batteryEntryForAOD_containCorrectInfo() {
final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application,
- BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY, 200, 100, 1000);
+ BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY,
+ /* devicePowerMah= */ 200,
+ /* usageDurationMs= */ 1000);
assertThat(entry.mIconId).isEqualTo(R.drawable.ic_settings_aod);
assertThat(entry.mName).isEqualTo("Ambient display");
@@ -168,7 +178,9 @@
@Test
public void batteryEntryForCustomComponent_containCorrectInfo() {
final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application,
- BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + 42, "ABC", 200, 100);
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + 42,
+ /* powerComponentName= */ "ABC",
+ /* devicePowerMah= */ 200);
assertThat(entry.mIconId).isEqualTo(R.drawable.ic_power_system);
assertThat(entry.mName).isEqualTo("ABC");
@@ -188,7 +200,9 @@
@Test
public void getTimeInForegroundMs_aggregateBatteryConsumer() {
final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application,
- BatteryConsumer.POWER_COMPONENT_BLUETOOTH, 10, 20, 100);
+ BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
+ /* devicePowerMah= */ 10,
+ /* usageDurationMs= */ 100);
assertThat(entry.getTimeInForegroundMs()).isEqualTo(100L);
}
@@ -207,7 +221,9 @@
@Test
public void getTimeInBackgroundMs_systemConsumer() {
final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application,
- BatteryConsumer.POWER_COMPONENT_BLUETOOTH, 100, 200, 1000);
+ BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
+ /* devicePowerMah= */ 100,
+ /* usageDurationMs= */ 1000);
assertThat(entry.getTimeInBackgroundMs()).isEqualTo(0);
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntryTest.java
index 848265a..5c143b1 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntryTest.java
@@ -63,7 +63,6 @@
when(mMockBatteryEntry.getConsumedPowerInCached()).thenReturn(1.5);
mMockBatteryEntry.mPercent = 0.3;
when(mMockBatteryEntry.getTimeInForegroundMs()).thenReturn(1234L);
- when(mMockBatteryEntry.getTimeInForegroundServiceMs()).thenReturn(3456L);
when(mMockBatteryEntry.getTimeInBackgroundMs()).thenReturn(5689L);
when(mMockBatteryEntry.getPowerComponentId()).thenReturn(expectedType);
when(mMockBatteryEntry.getConsumerType())
@@ -104,7 +103,6 @@
/*backgroundUsageConsumePower=*/ 1.4,
/*cachedUsageConsumePower=*/ 1.5,
/*foregroundUsageTimeInMs=*/ 1234L,
- /*foregroundServiceUsageTimeInMs=*/ 3456L,
/*backgroundUsageTimeInMs=*/ 5689L,
/*batteryLevel=*/ 12),
/*drainType=*/ 3,
@@ -193,7 +191,6 @@
/*backgroundUsageConsumePower=*/ 3,
/*cachedUsageConsumePower=*/ 4,
/*foregroundUsageTimeInMs=*/ 100,
- /*foregroundServiceUsageTimeInMs=*/ 150,
/*backgroundUsageTimeInMs=*/ 200,
/*batteryLevel=*/ 90);
final BatteryHistEntry upperHistEntry = createBatteryHistEntry(
@@ -206,7 +203,6 @@
/*backgroundUsageConsumePower=*/ 6,
/*cachedUsageConsumePower=*/ 5,
/*foregroundUsageTimeInMs=*/ 200,
- /*foregroundServiceUsageTimeInMs=*/ 250,
/*backgroundUsageTimeInMs=*/ 300,
/*batteryLevel=*/ 80);
@@ -229,7 +225,6 @@
/*backgroundUsageConsumePower=*/ 3 + 0.5 * (6 - 3),
/*cachedUsageConsumePower=*/ 4 + 0.5 * (5 - 4),
/*foregroundUsageTimeInMs=*/ Math.round(100 + 0.5 * (200 - 100)),
- /*foregroundServiceUsageTimeInMs=*/ Math.round(150 + 0.5 * (250 - 150)),
/*backgroundUsageTimeInMs=*/ Math.round(200 + 0.5 * (300 - 200)),
/*batteryLevel=*/ (int) Math.round(90 + 0.5 * (80 - 90)));
}
@@ -249,7 +244,6 @@
/*backgroundUsageConsumePower=*/ 6,
/*cachedUsageConsumePower=*/ 5,
/*foregroundUsageTimeInMs=*/ 200,
- /*foregroundServiceUsageTimeInMs=*/ 250,
/*backgroundUsageTimeInMs=*/ 300,
/*batteryLevel=*/ 80);
@@ -272,7 +266,6 @@
/*backgroundUsageConsumePower=*/ 0.5 * 6,
/*cachedUsageConsumePower=*/ 0.5 * 5,
/*foregroundUsageTimeInMs=*/ Math.round(0.5 * 200),
- /*foregroundServiceUsageTimeInMs=*/ Math.round(0.5 * 250),
/*backgroundUsageTimeInMs=*/ Math.round(0.5 * 300),
/*batteryLevel=*/ upperHistEntry.mBatteryLevel);
}
@@ -301,7 +294,6 @@
/*backgroundUsageConsumePower=*/ 1.4,
/*cachedUsageConsumePower=*/ 1.5,
/*foregroundUsageTimeInMs=*/ 1234L,
- /*foregroundServiceUsageTimeInMs=*/ 3456L,
/*backgroundUsageTimeInMs=*/ 5689L,
/*batteryLevel=*/ 12);
}
@@ -319,7 +311,6 @@
double backgroundUsageConsumePower,
double cachedUsageConsumePower,
long foregroundUsageTimeInMs,
- long foregroundServiceUsageTimeInMs,
long backgroundUsageTimeInMs,
int batteryLevel) {
assertThat(entry.isValidEntry()).isTrue();
@@ -341,8 +332,6 @@
assertThat(entry.mCachedUsageConsumePower).isEqualTo(cachedUsageConsumePower);
assertThat(entry.mPercentOfTotal).isEqualTo(percentOfTotal);
assertThat(entry.mForegroundUsageTimeInMs).isEqualTo(foregroundUsageTimeInMs);
- assertThat(entry.mForegroundServiceUsageTimeInMs)
- .isEqualTo(foregroundServiceUsageTimeInMs);
assertThat(entry.mBackgroundUsageTimeInMs).isEqualTo(backgroundUsageTimeInMs);
assertThat(entry.mDrainType).isEqualTo(drainType);
assertThat(entry.mConsumerType)
@@ -364,7 +353,6 @@
double backgroundUsageConsumePower,
double cachedUsageConsumePower,
long foregroundUsageTimeInMs,
- long foregroundServiceUsageTimeInMs,
long backgroundUsageTimeInMs,
int batteryLevel) {
final MatrixCursor cursor = new MatrixCursor(
@@ -399,7 +387,6 @@
.setPercentOfTotal(0.3)
.setDrainType(3)
.setForegroundUsageTimeInMs(foregroundUsageTimeInMs)
- .setForegroundServiceUsageTimeInMs(foregroundServiceUsageTimeInMs)
.setBackgroundUsageTimeInMs(backgroundUsageTimeInMs)
.build();
cursor.addRow(
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
new file mode 100644
index 0000000..0bc8693
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge.batteryusage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.LocaleList;
+import android.text.format.DateUtils;
+
+import androidx.preference.PreferenceGroup;
+
+import com.android.settings.SettingsActivity;
+import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.TimeZone;
+
+@RunWith(RobolectricTestRunner.class)
+public final class BatteryUsageBreakdownControllerTest {
+ private static final String PREF_KEY = "pref_key";
+ private static final String PREF_SUMMARY = "fake preference summary";
+
+ @Mock
+ private InstrumentedPreferenceFragment mFragment;
+ @Mock
+ private SettingsActivity mSettingsActivity;
+ @Mock
+ private PreferenceGroup mAppListPreferenceGroup;
+ @Mock
+ private Drawable mDrawable;
+ @Mock
+ private BatteryHistEntry mBatteryHistEntry;
+ @Mock
+ private PowerGaugePreference mPowerGaugePreference;
+
+ private Context mContext;
+ private FakeFeatureFactory mFeatureFactory;
+ private BatteryDiffEntry mBatteryDiffEntry;
+ private MetricsFeatureProvider mMetricsFeatureProvider;
+ private BatteryUsageBreakdownController mBatteryUsageBreakdownController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ Locale.setDefault(new Locale("en_US"));
+ org.robolectric.shadows.ShadowSettings.set24HourTimeFormat(false);
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
+ mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
+ mContext = spy(RuntimeEnvironment.application);
+ final Resources resources = spy(mContext.getResources());
+ resources.getConfiguration().setLocales(new LocaleList(new Locale("en_US")));
+ doReturn(resources).when(mContext).getResources();
+ doReturn(new String[]{"com.android.gms.persistent"})
+ .when(mFeatureFactory.powerUsageFeatureProvider)
+ .getHideApplicationEntries(mContext);
+ mBatteryUsageBreakdownController = createController();
+ mBatteryUsageBreakdownController.mAppListPreferenceGroup = mAppListPreferenceGroup;
+ mBatteryDiffEntry = new BatteryDiffEntry(
+ mContext,
+ /*foregroundUsageTimeInMs=*/ 1,
+ /*backgroundUsageTimeInMs=*/ 2,
+ /*consumePower=*/ 3,
+ /*foregroundUsageConsumePower=*/ 0,
+ /*foregroundServiceUsageConsumePower=*/ 1,
+ /*backgroundUsageConsumePower=*/ 2,
+ /*cachedUsageConsumePower=*/ 0,
+ mBatteryHistEntry);
+ mBatteryDiffEntry = spy(mBatteryDiffEntry);
+ mBatteryUsageBreakdownController.mBatteryDiffData =
+ new BatteryDiffData(Arrays.asList(mBatteryDiffEntry), Arrays.asList());
+ // Adds fake testing data.
+ BatteryDiffEntry.sResourceCache.put(
+ "fakeBatteryDiffEntryKey",
+ new BatteryEntry.NameAndIcon("fakeName", /*icon=*/ null, /*iconId=*/ 1));
+ }
+
+ @Test
+ public void onDestroy_clearPreferenceCacheAndPreferenceGroupRemoveAll() {
+ // Ensures the testing environment is correct.
+ mBatteryUsageBreakdownController.mPreferenceCache.put(
+ PREF_KEY, mPowerGaugePreference);
+ assertThat(mBatteryUsageBreakdownController.mPreferenceCache).hasSize(1);
+
+ mBatteryUsageBreakdownController.onDestroy();
+
+ assertThat(mBatteryUsageBreakdownController.mPreferenceCache).isEmpty();
+ }
+
+ @Test
+ public void onDestroy_removeAllPreferenceFromPreferenceGroup() {
+ mBatteryUsageBreakdownController.onDestroy();
+ verify(mAppListPreferenceGroup).removeAll();
+ }
+
+ @Test
+ public void addAllPreferences_addAllPreferences() {
+ final String appLabel = "fake app label";
+ doReturn(1).when(mAppListPreferenceGroup).getPreferenceCount();
+ doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
+ doReturn(appLabel).when(mBatteryDiffEntry).getAppLabel();
+ doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
+ doReturn(null).when(mAppListPreferenceGroup).findPreference(PREF_KEY);
+ doReturn(false).when(mBatteryDiffEntry).validForRestriction();
+
+ mBatteryUsageBreakdownController.addAllPreferences();
+
+ // Verifies the preference cache.
+ final PowerGaugePreference pref =
+ (PowerGaugePreference) mBatteryUsageBreakdownController.mPreferenceCache
+ .get(PREF_KEY);
+ assertThat(pref).isNotNull();
+ // Verifies the added preference configuration.
+ verify(mAppListPreferenceGroup).addPreference(pref);
+ assertThat(pref.getKey()).isEqualTo(PREF_KEY);
+ assertThat(pref.getTitle().toString()).isEqualTo(appLabel);
+ assertThat(pref.getIcon()).isEqualTo(mDrawable);
+ assertThat(pref.getOrder()).isEqualTo(1);
+ assertThat(pref.getBatteryDiffEntry()).isSameInstanceAs(mBatteryDiffEntry);
+ assertThat(pref.isSingleLineTitle()).isTrue();
+ assertThat(pref.isEnabled()).isFalse();
+ }
+
+ @Test
+ public void addPreferenceToScreen_alreadyInScreen_notAddPreferenceAgain() {
+ final String appLabel = "fake app label";
+ doReturn(1).when(mAppListPreferenceGroup).getPreferenceCount();
+ doReturn(mDrawable).when(mBatteryDiffEntry).getAppIcon();
+ doReturn(appLabel).when(mBatteryDiffEntry).getAppLabel();
+ doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
+ doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).findPreference(PREF_KEY);
+
+ mBatteryUsageBreakdownController.addAllPreferences();
+
+ verify(mAppListPreferenceGroup, never()).addPreference(any());
+ }
+
+ @Test
+ public void removeAndCacheAllPreferences_buildCacheAndRemoveAllPreference() {
+ doReturn(1).when(mAppListPreferenceGroup).getPreferenceCount();
+ doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).getPreference(0);
+ doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
+ doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
+ doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).findPreference(PREF_KEY);
+ // Ensures the testing data is correct.
+ assertThat(mBatteryUsageBreakdownController.mPreferenceCache).isEmpty();
+
+ mBatteryUsageBreakdownController.removeAndCacheAllPreferences();
+
+ assertThat(mBatteryUsageBreakdownController.mPreferenceCache.get(PREF_KEY))
+ .isEqualTo(mPowerGaugePreference);
+ verify(mAppListPreferenceGroup).removeAll();
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_notPowerGaugePreference_returnFalse() {
+ assertThat(mBatteryUsageBreakdownController
+ .handlePreferenceTreeClick(mAppListPreferenceGroup)).isFalse();
+
+ verify(mMetricsFeatureProvider, never())
+ .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_APP_ITEM);
+ verify(mMetricsFeatureProvider, never())
+ .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SYSTEM_ITEM);
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_forAppEntry_returnTrue() {
+ doReturn(false).when(mBatteryHistEntry).isAppEntry();
+ doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
+
+ assertThat(mBatteryUsageBreakdownController.handlePreferenceTreeClick(
+ mPowerGaugePreference)).isTrue();
+ verify(mMetricsFeatureProvider)
+ .action(
+ SettingsEnums.OPEN_BATTERY_USAGE,
+ SettingsEnums.ACTION_BATTERY_USAGE_SYSTEM_ITEM,
+ SettingsEnums.OPEN_BATTERY_USAGE,
+ /* package name */ "none",
+ /* percentage of total */ 100);
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_forSystemEntry_returnTrue() {
+ doReturn(true).when(mBatteryHistEntry).isAppEntry();
+ doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
+
+ assertThat(mBatteryUsageBreakdownController.handlePreferenceTreeClick(
+ mPowerGaugePreference)).isTrue();
+ verify(mMetricsFeatureProvider)
+ .action(
+ SettingsEnums.OPEN_BATTERY_USAGE,
+ SettingsEnums.ACTION_BATTERY_USAGE_APP_ITEM,
+ SettingsEnums.OPEN_BATTERY_USAGE,
+ /* package name */ "none",
+ /* percentage of total */ 100);
+ }
+
+ @Test
+ public void setPreferenceSummary_setNullContentIfTotalUsageTimeIsZero() {
+ final PowerGaugePreference pref = new PowerGaugePreference(mContext);
+ pref.setSummary(PREF_SUMMARY);
+
+ mBatteryUsageBreakdownController.setPreferenceSummary(
+ pref, createBatteryDiffEntry(
+ /*foregroundUsageTimeInMs=*/ 0,
+ /*backgroundUsageTimeInMs=*/ 0));
+ assertThat(pref.getSummary()).isNull();
+ }
+
+ @Test
+ public void setPreferenceSummary_setBackgroundUsageTimeOnly() {
+ final PowerGaugePreference pref = new PowerGaugePreference(mContext);
+ pref.setSummary(PREF_SUMMARY);
+
+ mBatteryUsageBreakdownController.setPreferenceSummary(
+ pref, createBatteryDiffEntry(
+ /*foregroundUsageTimeInMs=*/ 0,
+ /*backgroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS));
+ assertThat(pref.getSummary().toString()).isEqualTo("Background: 1 min");
+ }
+
+ @Test
+ public void setPreferenceSummary_setTotalUsageTimeLessThanAMinute() {
+ final PowerGaugePreference pref = new PowerGaugePreference(mContext);
+ pref.setSummary(PREF_SUMMARY);
+
+ mBatteryUsageBreakdownController.setPreferenceSummary(
+ pref, createBatteryDiffEntry(
+ /*foregroundUsageTimeInMs=*/ 100,
+ /*backgroundUsageTimeInMs=*/ 200));
+ assertThat(pref.getSummary().toString()).isEqualTo("Total: less than a min");
+ }
+
+ @Test
+ public void setPreferenceSummary_setTotalTimeIfBackgroundTimeLessThanAMinute() {
+ final PowerGaugePreference pref = new PowerGaugePreference(mContext);
+ pref.setSummary(PREF_SUMMARY);
+
+ mBatteryUsageBreakdownController.setPreferenceSummary(
+ pref, createBatteryDiffEntry(
+ /*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
+ /*backgroundUsageTimeInMs=*/ 200));
+ assertThat(pref.getSummary().toString())
+ .isEqualTo("Total: 1 min\nBackground: less than a min");
+ }
+
+ @Test
+ public void setPreferenceSummary_setTotalAndBackgroundUsageTime() {
+ final PowerGaugePreference pref = new PowerGaugePreference(mContext);
+ pref.setSummary(PREF_SUMMARY);
+
+ mBatteryUsageBreakdownController.setPreferenceSummary(
+ pref, createBatteryDiffEntry(
+ /*foregroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS,
+ /*backgroundUsageTimeInMs=*/ DateUtils.MINUTE_IN_MILLIS));
+ assertThat(pref.getSummary().toString()).isEqualTo("Total: 2 min\nBackground: 1 min");
+ }
+
+ private BatteryDiffEntry createBatteryDiffEntry(
+ long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) {
+ return new BatteryDiffEntry(
+ mContext, foregroundUsageTimeInMs, backgroundUsageTimeInMs, /*consumePower=*/ 0,
+ /*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
+ /*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
+ mBatteryHistEntry);
+ }
+
+ private BatteryUsageBreakdownController createController() {
+ final BatteryUsageBreakdownController controller =
+ new BatteryUsageBreakdownController(
+ mContext, /*lifecycle=*/ null, mSettingsActivity, mFragment);
+ controller.mPrefContext = mContext;
+ return controller;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProviderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProviderTest.java
index d6e7737..d578b89 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProviderTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageContentProviderTest.java
@@ -202,7 +202,6 @@
.setCachedUsageConsumePower(3)
.setPercentOfTotal(0.9)
.setForegroundUsageTimeInMs(1000)
- .setForegroundServiceUsageTimeInMs(1500)
.setBackgroundUsageTimeInMs(2000)
.setDrainType(1)
.build();
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
index 9a43557..978930a 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ConvertUtilsTest.java
@@ -70,7 +70,6 @@
when(mMockBatteryEntry.getConsumedPowerInCached()).thenReturn(1.5);
mMockBatteryEntry.mPercent = 0.3;
when(mMockBatteryEntry.getTimeInForegroundMs()).thenReturn(1234L);
- when(mMockBatteryEntry.getTimeInForegroundServiceMs()).thenReturn(3456L);
when(mMockBatteryEntry.getTimeInBackgroundMs()).thenReturn(5689L);
when(mMockBatteryEntry.getPowerComponentId()).thenReturn(expectedType);
when(mMockBatteryEntry.getConsumerType())
@@ -112,7 +111,6 @@
assertThat(batteryInformation.getCachedUsageConsumePower()).isEqualTo(1.5);
assertThat(batteryInformation.getPercentOfTotal()).isEqualTo(0.3);
assertThat(batteryInformation.getForegroundUsageTimeInMs()).isEqualTo(1234L);
- assertThat(batteryInformation.getForegroundServiceUsageTimeInMs()).isEqualTo(3456L);
assertThat(batteryInformation.getBackgroundUsageTimeInMs()).isEqualTo(5689L);
assertThat(batteryInformation.getDrainType()).isEqualTo(expectedType);
assertThat(deviceBatteryState.getBatteryLevel()).isEqualTo(12);
@@ -169,7 +167,6 @@
when(mMockBatteryEntry.getConsumedPowerInCached()).thenReturn(1.5);
mMockBatteryEntry.mPercent = 0.3;
when(mMockBatteryEntry.getTimeInForegroundMs()).thenReturn(1234L);
- when(mMockBatteryEntry.getTimeInForegroundServiceMs()).thenReturn(3456L);
when(mMockBatteryEntry.getTimeInBackgroundMs()).thenReturn(5689L);
when(mMockBatteryEntry.getPowerComponentId()).thenReturn(expectedType);
when(mMockBatteryEntry.getConsumerType())
@@ -202,8 +199,6 @@
assertThat(batteryHistEntry.mPercentOfTotal).isEqualTo(0.3);
assertThat(batteryHistEntry.mForegroundUsageTimeInMs)
.isEqualTo(1234L);
- assertThat(batteryHistEntry.mForegroundServiceUsageTimeInMs)
- .isEqualTo(3456L);
assertThat(batteryHistEntry.mBackgroundUsageTimeInMs)
.isEqualTo(5689L);
assertThat(batteryHistEntry.mDrainType).isEqualTo(expectedType);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
index cdfed06..5b69e7c 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
@@ -18,7 +18,10 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -27,7 +30,9 @@
import android.app.settings.SettingsEnums;
import android.content.ContentValues;
import android.content.Context;
+import android.content.Intent;
import android.os.BatteryConsumer;
+import android.os.BatteryManager;
import android.os.BatteryUsageStats;
import android.text.format.DateUtils;
@@ -63,6 +68,7 @@
private MetricsFeatureProvider mMetricsFeatureProvider;
private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
+ @Mock private Intent mIntent;
@Mock private BatteryUsageStats mBatteryUsageStats;
@Mock private BatteryEntry mMockBatteryEntry1;
@Mock private BatteryEntry mMockBatteryEntry2;
@@ -79,6 +85,10 @@
mFeatureFactory = FakeFeatureFactory.setupForTest();
mMetricsFeatureProvider = mFeatureFactory.metricsFeatureProvider;
mPowerUsageFeatureProvider = mFeatureFactory.powerUsageFeatureProvider;
+
+ doReturn(mIntent).when(mContext).registerReceiver(any(), any());
+ doReturn(100).when(mIntent).getIntExtra(eq(BatteryManager.EXTRA_SCALE), anyInt());
+ doReturn(66).when(mIntent).getIntExtra(eq(BatteryManager.EXTRA_LEVEL), anyInt());
}
@Test
@@ -100,11 +110,15 @@
@Test
public void getBatteryLevelData_notEnoughData_returnNull() {
- // The timestamps are within 1 hour.
- final long[] timestamps = {1000000L, 2000000L, 3000000L};
+ // The timestamps and the current time are within half hour before an even hour.
+ final long[] timestamps = {
+ DateUtils.HOUR_IN_MILLIS * 2 - 300L,
+ DateUtils.HOUR_IN_MILLIS * 2 - 200L,
+ DateUtils.HOUR_IN_MILLIS * 2 - 100L};
final int[] levels = {100, 99, 98};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
createHistoryMap(timestamps, levels);
+ DataProcessor.sFakeCurrentTimeMillis = timestamps[timestamps.length - 1];
assertThat(DataProcessor.getBatteryLevelData(
mContext, /*handler=*/ null, batteryHistoryMap, /*asyncResponseDelegate=*/ null))
@@ -117,11 +131,12 @@
@Test
public void getBatteryLevelData_returnExpectedResult() {
- // Timezone GMT+8: 2022-01-01 00:00:00, 2022-01-01 01:00:00, 2022-01-01 02:00:00
- final long[] timestamps = {1640966400000L, 1640970000000L, 1640973600000L};
- final int[] levels = {100, 99, 98};
+ // Timezone GMT+8: 2022-01-01 00:00:00, 2022-01-01 01:00:00
+ final long[] timestamps = {1640966400000L, 1640970000000L};
+ final int[] levels = {100, 99};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
createHistoryMap(timestamps, levels);
+ DataProcessor.sFakeCurrentTimeMillis = timestamps[timestamps.length - 1];
final BatteryLevelData resultData =
DataProcessor.getBatteryLevelData(
@@ -130,8 +145,10 @@
batteryHistoryMap,
/*asyncResponseDelegate=*/ null);
- final List<Long> expectedDailyTimestamps = List.of(timestamps[0], timestamps[2]);
- final List<Integer> expectedDailyLevels = List.of(levels[0], levels[2]);
+ final List<Long> expectedDailyTimestamps = List.of(
+ 1640966400000L, // 2022-01-01 00:00:00
+ 1640973600000L); // 2022-01-01 02:00:00
+ final List<Integer> expectedDailyLevels = List.of(100, 66);
final List<List<Long>> expectedHourlyTimestamps = List.of(expectedDailyTimestamps);
final List<List<Integer>> expectedHourlyLevels = List.of(expectedDailyLevels);
verifyExpectedBatteryLevelData(
@@ -162,6 +179,7 @@
final int[] levels = {100, 94, 90, 82, 50};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
createHistoryMap(timestamps, levels);
+ DataProcessor.sFakeCurrentTimeMillis = timestamps[timestamps.length - 1];
final Map<Long, Map<String, BatteryHistEntry>> resultMap =
DataProcessor.getHistoryMapWithExpectedTimestamps(mContext, batteryHistoryMap);
@@ -172,14 +190,20 @@
1640970000000L, // 2022-01-01 01:00:00
1640973600000L, // 2022-01-01 02:00:00
1640977200000L, // 2022-01-01 03:00:00
- 1640980800000L // 2022-01-01 04:00:00
+ 1640980800000L, // 2022-01-01 04:00:00
+ 1640984400000L, // 2022-01-01 05:00:00
+ 1640988000000L // 2022-01-01 06:00:00
};
- final int[] expectedLevels = {100, 94, 90, 84, 56};
+ final int[] expectedLevels = {100, 94, 90, 84, 56, 98, 98};
assertThat(resultMap).hasSize(expectedLevels.length);
- for (int index = 0; index < expectedLevels.length; index++) {
+ for (int index = 0; index < 5; index++) {
assertThat(resultMap.get(expectedTimestamps[index]).get(FAKE_ENTRY_KEY).mBatteryLevel)
.isEqualTo(expectedLevels[index]);
}
+ for (int index = 5; index < 7; index++) {
+ assertThat(resultMap.get(expectedTimestamps[index]).containsKey(
+ DataProcessor.CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER)).isTrue();
+ }
}
@Test
@@ -188,6 +212,7 @@
final int[] levels = {100};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
createHistoryMap(timestamps, levels);
+ DataProcessor.sFakeCurrentTimeMillis = timestamps[timestamps.length - 1];
assertThat(
DataProcessor.getLevelDataThroughProcessedHistoryMap(mContext, batteryHistoryMap))
@@ -207,6 +232,7 @@
final int[] levels = {100, 94, 90, 82, 50};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
createHistoryMap(timestamps, levels);
+ DataProcessor.sFakeCurrentTimeMillis = timestamps[timestamps.length - 1];
final BatteryLevelData resultData =
DataProcessor.getLevelDataThroughProcessedHistoryMap(mContext, batteryHistoryMap);
@@ -239,6 +265,7 @@
final int[] levels = {100, 94, 90, 82};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
createHistoryMap(timestamps, levels);
+ DataProcessor.sFakeCurrentTimeMillis = timestamps[timestamps.length - 1];
final BatteryLevelData resultData =
DataProcessor.getLevelDataThroughProcessedHistoryMap(mContext, batteryHistoryMap);
@@ -290,8 +317,8 @@
@Test
public void getTimestampSlots_emptyRawList_returnEmptyList() {
- final List<Long> resultList =
- DataProcessor.getTimestampSlots(new ArrayList<>());
+ final List<Long> resultList = DataProcessor.getTimestampSlots(
+ new ArrayList<>(), 1641038400000L); // 2022-01-01 20:00:00
assertThat(resultList).isEmpty();
}
@@ -305,7 +332,7 @@
final Calendar expectedStartCalendar = Calendar.getInstance();
expectedStartCalendar.set(2022, 6, 5, 6, 0, 0); // 2022-07-05 06:00:00
final Calendar expectedEndCalendar = Calendar.getInstance();
- expectedEndCalendar.set(2022, 6, 5, 22, 0, 0); // 2022-07-05 22:00:00
+ expectedEndCalendar.set(2022, 6, 6, 0, 0, 0); // 2022-07-05 22:00:00
verifyExpectedTimestampSlots(
startCalendar, endCalendar, expectedStartCalendar, expectedEndCalendar);
}
@@ -320,7 +347,7 @@
final Calendar expectedStartCalendar = Calendar.getInstance();
expectedStartCalendar.set(2022, 6, 5, 6, 00, 00); // 2022-07-05 06:00:00
final Calendar expectedEndCalendar = Calendar.getInstance();
- expectedEndCalendar.set(2022, 6, 6, 20, 00, 00); // 2022-07-06 20:00:00
+ expectedEndCalendar.set(2022, 6, 6, 22, 00, 00); // 2022-07-06 20:00:00
verifyExpectedTimestampSlots(
startCalendar, endCalendar, expectedStartCalendar, expectedEndCalendar);
}
@@ -536,8 +563,7 @@
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 0L, currentUserId, ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
- /*foregroundUsageTimeInMs=*/ 0L, /*foregroundServiceUsageTimeInMs=*/ 0L,
- /*backgroundUsageTimeInMs=*/ 0L);
+ /*foregroundUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L);
// Adds the index = 0 data.
Map<String, BatteryHistEntry> entryMap = new HashMap<>();
BatteryHistEntry entry = createBatteryHistEntry(
@@ -546,7 +572,7 @@
/*backgroundUsageConsumePower=*/ 3, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
- /*foregroundServiceUsageTimeInMs=*/ 10L, /*backgroundUsageTimeInMs=*/ 20L);
+ /*backgroundUsageTimeInMs=*/ 20L);
entryMap.put(entry.getKey(), entry);
entryMap.put(fakeEntry.getKey(), fakeEntry);
batteryHistoryMap.put(batteryHistoryKeys[0], entryMap);
@@ -562,7 +588,7 @@
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 15L,
- /*foregroundServiceUsageTimeInMs=*/ 15L, /*backgroundUsageTimeInMs=*/ 25L);
+ /*backgroundUsageTimeInMs=*/ 25L);
entryMap.put(entry.getKey(), entry);
entryMap.put(fakeEntry.getKey(), fakeEntry);
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
@@ -574,7 +600,7 @@
/*backgroundUsageConsumePower=*/ 8, /*cachedUsageConsumePower=*/ 8,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 25L,
- /*foregroundServiceUsageTimeInMs=*/ 25L, /*backgroundUsageTimeInMs=*/ 35L);
+ /*backgroundUsageTimeInMs=*/ 35L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 10.0,
@@ -582,7 +608,7 @@
/*backgroundUsageConsumePower=*/ 2, /*cachedUsageConsumePower=*/ 2,
/*uid=*/ 3L, currentUserId,
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*foregroundUsageTimeInMs=*/ 40L,
- /*foregroundServiceUsageTimeInMs=*/ 40L, /*backgroundUsageTimeInMs=*/ 50L);
+ /*backgroundUsageTimeInMs=*/ 50L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package3", "label3", /*consumePower=*/ 15.0,
@@ -590,7 +616,7 @@
/*backgroundUsageConsumePower=*/ 3, /*cachedUsageConsumePower=*/ 3,
/*uid=*/ 4L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 5L,
- /*foregroundServiceUsageTimeInMs=*/ 5L, /*backgroundUsageTimeInMs=*/ 5L);
+ /*backgroundUsageTimeInMs=*/ 5L);
entryMap.put(entry.getKey(), entry);
entryMap.put(fakeEntry.getKey(), fakeEntry);
batteryHistoryMap.put(batteryHistoryKeys[3], entryMap);
@@ -602,7 +628,7 @@
/*backgroundUsageConsumePower=*/ 9, /*cachedUsageConsumePower=*/ 8,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 30L,
- /*foregroundServiceUsageTimeInMs=*/ 30L, /*backgroundUsageTimeInMs=*/ 40L);
+ /*backgroundUsageTimeInMs=*/ 40L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 20.0,
@@ -610,7 +636,7 @@
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
/*uid=*/ 3L, currentUserId,
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*foregroundUsageTimeInMs=*/ 50L,
- /*foregroundServiceUsageTimeInMs=*/ 50L, /*backgroundUsageTimeInMs=*/ 60L);
+ /*backgroundUsageTimeInMs=*/ 60L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package3", "label3", /*consumePower=*/ 40.0,
@@ -618,7 +644,7 @@
/*backgroundUsageConsumePower=*/ 8, /*cachedUsageConsumePower=*/ 8,
/*uid=*/ 4L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 5L,
- /*foregroundServiceUsageTimeInMs=*/ 5L, /*backgroundUsageTimeInMs=*/ 5L);
+ /*backgroundUsageTimeInMs=*/ 5L);
entryMap.put(entry.getKey(), entry);
entryMap.put(fakeEntry.getKey(), fakeEntry);
batteryHistoryMap.put(batteryHistoryKeys[4], entryMap);
@@ -645,55 +671,48 @@
.get(DataProcessor.SELECTED_INDEX_ALL);
assertBatteryDiffEntry(
resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 2L,
- ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 40.0,
+ ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 50.0,
/*foregroundUsageConsumePower=*/ 14, /*foregroundServiceUsageConsumePower=*/ 9,
/*backgroundUsageConsumePower=*/ 9, /*cachedUsageConsumePower=*/ 8,
- /*foregroundUsageTimeInMs=*/ 30, /*foregroundServiceUsageTimeInMs=*/ 30,
- /*backgroundUsageTimeInMs=*/ 40);
+ /*foregroundUsageTimeInMs=*/ 30, /*backgroundUsageTimeInMs=*/ 40);
assertBatteryDiffEntry(
resultDiffData.getAppDiffEntryList().get(1), currentUserId, /*uid=*/ 4L,
- ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 40.0,
+ ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 50.0,
/*foregroundUsageConsumePower=*/ 8, /*foregroundServiceUsageConsumePower=*/ 8,
/*backgroundUsageConsumePower=*/ 8, /*cachedUsageConsumePower=*/ 8,
- /*foregroundUsageTimeInMs=*/ 5, /*foregroundServiceUsageTimeInMs=*/ 5,
- /*backgroundUsageTimeInMs=*/ 5);
+ /*foregroundUsageTimeInMs=*/ 5, /*backgroundUsageTimeInMs=*/ 5);
assertBatteryDiffEntry(
resultDiffData.getSystemDiffEntryList().get(0), currentUserId, /*uid=*/ 3L,
- ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*consumePercentage=*/ 20.0,
+ ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*consumePercentage=*/ 100.0,
/*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 5,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
- /*foregroundUsageTimeInMs=*/ 50, /*foregroundServiceUsageTimeInMs=*/ 50,
- /*backgroundUsageTimeInMs=*/ 60);
+ /*foregroundUsageTimeInMs=*/ 50, /*backgroundUsageTimeInMs=*/ 60);
resultDiffData = resultMap.get(0).get(DataProcessor.SELECTED_INDEX_ALL);
assertBatteryDiffEntry(
resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 2L,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 100.0,
/*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 5,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
- /*foregroundUsageTimeInMs=*/ 15, /*foregroundServiceUsageTimeInMs=*/ 15,
- /*backgroundUsageTimeInMs=*/ 25);
+ /*foregroundUsageTimeInMs=*/ 15, /*backgroundUsageTimeInMs=*/ 25);
resultDiffData = resultMap.get(1).get(DataProcessor.SELECTED_INDEX_ALL);
assertBatteryDiffEntry(
resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 4L,
- ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 50.0,
+ ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 66.66666666666666,
/*foregroundUsageConsumePower=*/ 8, /*foregroundServiceUsageConsumePower=*/ 8,
/*backgroundUsageConsumePower=*/ 8, /*cachedUsageConsumePower=*/ 8,
- /*foregroundUsageTimeInMs=*/ 5, /*foregroundServiceUsageTimeInMs=*/ 5,
- /*backgroundUsageTimeInMs=*/ 5);
+ /*foregroundUsageTimeInMs=*/ 5, /*backgroundUsageTimeInMs=*/ 5);
assertBatteryDiffEntry(
resultDiffData.getAppDiffEntryList().get(1), currentUserId, /*uid=*/ 2L,
- ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 25.0,
+ ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 33.33333333333333,
/*foregroundUsageConsumePower=*/ 9, /*foregroundServiceUsageConsumePower=*/ 4,
/*backgroundUsageConsumePower=*/ 4, /*cachedUsageConsumePower=*/ 3,
- /*foregroundUsageTimeInMs=*/ 15, /*foregroundServiceUsageTimeInMs=*/ 15,
- /*backgroundUsageTimeInMs=*/ 15);
+ /*foregroundUsageTimeInMs=*/ 15, /*backgroundUsageTimeInMs=*/ 15);
assertBatteryDiffEntry(
resultDiffData.getSystemDiffEntryList().get(0), currentUserId, /*uid=*/ 3L,
- ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*consumePercentage=*/ 25.0,
+ ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*consumePercentage=*/ 100.0,
/*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 5,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
- /*foregroundUsageTimeInMs=*/ 50, /*foregroundServiceUsageTimeInMs=*/ 50,
- /*backgroundUsageTimeInMs=*/ 60);
+ /*foregroundUsageTimeInMs=*/ 50, /*backgroundUsageTimeInMs=*/ 60);
verify(mMetricsFeatureProvider)
.action(mContext.getApplicationContext(),
SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
@@ -721,7 +740,7 @@
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
- /*foregroundServiceUsageTimeInMs=*/ 10L, /*backgroundUsageTimeInMs=*/ 20L);
+ /*backgroundUsageTimeInMs=*/ 20L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 10.0,
@@ -729,7 +748,7 @@
/*backgroundUsageConsumePower=*/ 1, /*cachedUsageConsumePower=*/ 1,
/*uid=*/ 2L, currentUserId + 1,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
- /*foregroundServiceUsageTimeInMs=*/ 10L, /*backgroundUsageTimeInMs=*/ 20L);
+ /*backgroundUsageTimeInMs=*/ 20L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 5.0,
@@ -737,7 +756,7 @@
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 3L, currentUserId + 2,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 20L,
- /*foregroundServiceUsageTimeInMs=*/ 20L, /*backgroundUsageTimeInMs=*/ 30L);
+ /*backgroundUsageTimeInMs=*/ 30L);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[0], entryMap);
// Adds the index = 1 data.
@@ -748,7 +767,7 @@
/*backgroundUsageConsumePower=*/ 2, /*cachedUsageConsumePower=*/ 2,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 20L,
- /*foregroundServiceUsageTimeInMs=*/ 20L, /*backgroundUsageTimeInMs=*/ 30L);
+ /*backgroundUsageTimeInMs=*/ 30L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 30.0,
@@ -756,7 +775,7 @@
/*backgroundUsageConsumePower=*/ 2, /*cachedUsageConsumePower=*/ 2,
/*uid=*/ 2L, currentUserId + 1,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
- /*foregroundServiceUsageTimeInMs=*/ 10L, /*backgroundUsageTimeInMs=*/ 20L);
+ /*backgroundUsageTimeInMs=*/ 20L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 15.0,
@@ -764,7 +783,7 @@
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 3L, currentUserId + 2,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 30L,
- /*foregroundServiceUsageTimeInMs=*/ 30L, /*backgroundUsageTimeInMs=*/ 30L);
+ /*backgroundUsageTimeInMs=*/ 30L);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[1], entryMap);
// Adds the index = 2 data.
@@ -775,7 +794,7 @@
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 20L,
- /*foregroundServiceUsageTimeInMs=*/ 25L, /*backgroundUsageTimeInMs=*/ 30L);
+ /*backgroundUsageTimeInMs=*/ 30L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 50.0,
@@ -783,7 +802,7 @@
/*backgroundUsageConsumePower=*/ 10, /*cachedUsageConsumePower=*/ 10,
/*uid=*/ 2L, currentUserId + 1,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 20L,
- /*foregroundServiceUsageTimeInMs=*/ 25L, /*backgroundUsageTimeInMs=*/ 20L);
+ /*backgroundUsageTimeInMs=*/ 20L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 25.0,
@@ -791,7 +810,7 @@
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 3L, currentUserId + 2,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 30L,
- /*foregroundServiceUsageTimeInMs=*/ 35L, /*backgroundUsageTimeInMs=*/ 30L);
+ /*backgroundUsageTimeInMs=*/ 30L);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
@@ -811,19 +830,17 @@
.get(DataProcessor.SELECTED_INDEX_ALL);
assertBatteryDiffEntry(
resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 1L,
- ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 25.0,
+ ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 100.0,
/*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 5,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
- /*foregroundUsageTimeInMs=*/ 10, /*foregroundServiceUsageTimeInMs=*/ 15,
- /*backgroundUsageTimeInMs=*/ 10);
+ /*foregroundUsageTimeInMs=*/ 10, /*backgroundUsageTimeInMs=*/ 10);
assertBatteryDiffEntry(
resultDiffData.getSystemDiffEntryList().get(0), BatteryUtils.UID_OTHER_USERS,
/*uid=*/ BatteryUtils.UID_OTHER_USERS, ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
- /*consumePercentage=*/ 75.0,
+ /*consumePercentage=*/ 100.0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
- /*foregroundUsageTimeInMs=*/ 0, /*foregroundServiceUsageTimeInMs=*/ 0,
- /*backgroundUsageTimeInMs=*/ 0);
+ /*foregroundUsageTimeInMs=*/ 0, /*backgroundUsageTimeInMs=*/ 0);
assertThat(resultMap.get(0).get(0)).isNotNull();
assertThat(resultMap.get(0).get(DataProcessor.SELECTED_INDEX_ALL)).isNotNull();
verify(mMetricsFeatureProvider)
@@ -853,7 +870,7 @@
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
- /*foregroundServiceUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L);
+ /*backgroundUsageTimeInMs=*/ 0L);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[0], entryMap);
// Adds the index = 1 data.
@@ -864,7 +881,7 @@
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
- /*foregroundServiceUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L);
+ /*backgroundUsageTimeInMs=*/ 0L);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[1], entryMap);
// Adds the index = 2 data.
@@ -875,7 +892,6 @@
/*backgroundUsageConsumePower=*/ 100, /*cachedUsageConsumePower=*/ 100,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 3600000L,
- /*foregroundServiceUsageTimeInMs=*/ 1800000L,
/*backgroundUsageTimeInMs=*/ 7200000L);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
@@ -899,8 +915,6 @@
final BatteryDiffEntry resultEntry = resultDiffData.getAppDiffEntryList().get(0);
assertThat(resultEntry.mForegroundUsageTimeInMs)
.isEqualTo(Math.round(entry.mForegroundUsageTimeInMs * ratio));
- assertThat(resultEntry.mForegroundServiceUsageTimeInMs)
- .isEqualTo(Math.round(entry.mForegroundServiceUsageTimeInMs * ratio));
assertThat(resultEntry.mBackgroundUsageTimeInMs)
.isEqualTo(Math.round(entry.mBackgroundUsageTimeInMs * ratio));
assertThat(resultEntry.mConsumePower)
@@ -942,7 +956,7 @@
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
- /*foregroundServiceUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L);
+ /*backgroundUsageTimeInMs=*/ 0L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 0,
@@ -950,7 +964,7 @@
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
- /*foregroundServiceUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L);
+ /*backgroundUsageTimeInMs=*/ 0L);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[0], entryMap);
// Adds the index = 1 data.
@@ -961,7 +975,7 @@
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
- /*foregroundServiceUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L);
+ /*backgroundUsageTimeInMs=*/ 0L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 0,
@@ -969,7 +983,7 @@
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
- /*foregroundServiceUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L);
+ /*backgroundUsageTimeInMs=*/ 0L);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[1], entryMap);
// Adds the index = 2 data.
@@ -980,7 +994,7 @@
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
- /*foregroundServiceUsageTimeInMs=*/ 15L, /*backgroundUsageTimeInMs=*/ 20L);
+ /*backgroundUsageTimeInMs=*/ 20L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 10.0,
@@ -988,7 +1002,7 @@
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
- /*foregroundServiceUsageTimeInMs=*/ 15L, /*backgroundUsageTimeInMs=*/ 20L);
+ /*backgroundUsageTimeInMs=*/ 20L);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
@@ -1013,8 +1027,7 @@
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 50.0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
- /*foregroundUsageTimeInMs=*/ 10, /*foregroundServiceUsageTimeInMs=*/ 15,
- /*backgroundUsageTimeInMs=*/ 20);
+ /*foregroundUsageTimeInMs=*/ 10, /*backgroundUsageTimeInMs=*/ 20);
verify(mMetricsFeatureProvider)
.action(mContext.getApplicationContext(),
SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
@@ -1042,7 +1055,7 @@
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
- /*foregroundServiceUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L);
+ /*backgroundUsageTimeInMs=*/ 0L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 0,
@@ -1050,7 +1063,7 @@
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
- /*foregroundServiceUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L);
+ /*backgroundUsageTimeInMs=*/ 0L);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[0], entryMap);
// Adds the index = 1 data.
@@ -1061,7 +1074,7 @@
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
- /*foregroundServiceUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L);
+ /*backgroundUsageTimeInMs=*/ 0L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 0,
@@ -1069,7 +1082,7 @@
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
- /*foregroundServiceUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L);
+ /*backgroundUsageTimeInMs=*/ 0L);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[1], entryMap);
// Adds the index = 2 data.
@@ -1080,7 +1093,7 @@
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
- /*foregroundServiceUsageTimeInMs=*/ 15L, /*backgroundUsageTimeInMs=*/ 20L);
+ /*backgroundUsageTimeInMs=*/ 20L);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 10.0,
@@ -1088,7 +1101,7 @@
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
- /*foregroundServiceUsageTimeInMs=*/ 15L, /*backgroundUsageTimeInMs=*/ 20L);
+ /*backgroundUsageTimeInMs=*/ 20L);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
@@ -1124,8 +1137,8 @@
@Test
public void generateBatteryDiffData_emptyBatteryEntryList_returnNull() {
- assertThat(DataProcessor.generateBatteryDiffData(
- mContext, null, mBatteryUsageStats)).isNull();
+ assertThat(DataProcessor.generateBatteryDiffData(mContext,
+ DataProcessor.convertToBatteryHistEntry(null, mBatteryUsageStats))).isNull();
}
@Test
@@ -1141,7 +1154,6 @@
doReturn(0.0).when(mMockBatteryEntry1).getConsumedPowerInBackground();
doReturn(0.0).when(mMockBatteryEntry1).getConsumedPowerInCached();
doReturn(30L).when(mMockBatteryEntry1).getTimeInForegroundMs();
- doReturn(20L).when(mMockBatteryEntry1).getTimeInForegroundServiceMs();
doReturn(40L).when(mMockBatteryEntry1).getTimeInBackgroundMs();
doReturn(1).when(mMockBatteryEntry1).getUid();
doReturn(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).when(mMockBatteryEntry1).getConsumerType();
@@ -1151,7 +1163,6 @@
doReturn(0.0).when(mMockBatteryEntry2).getConsumedPowerInBackground();
doReturn(0.0).when(mMockBatteryEntry2).getConsumedPowerInCached();
doReturn(20L).when(mMockBatteryEntry2).getTimeInForegroundMs();
- doReturn(30L).when(mMockBatteryEntry2).getTimeInForegroundServiceMs();
doReturn(20L).when(mMockBatteryEntry2).getTimeInBackgroundMs();
doReturn(2).when(mMockBatteryEntry2).getUid();
doReturn(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).when(mMockBatteryEntry2).getConsumerType();
@@ -1161,7 +1172,6 @@
doReturn(0.0).when(mMockBatteryEntry3).getConsumedPowerInBackground();
doReturn(0.0).when(mMockBatteryEntry3).getConsumedPowerInCached();
doReturn(0L).when(mMockBatteryEntry3).getTimeInForegroundMs();
- doReturn(0L).when(mMockBatteryEntry3).getTimeInForegroundServiceMs();
doReturn(0L).when(mMockBatteryEntry3).getTimeInBackgroundMs();
doReturn(3).when(mMockBatteryEntry3).getUid();
doReturn(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).when(mMockBatteryEntry3).getConsumerType();
@@ -1171,7 +1181,6 @@
doReturn(0.3).when(mMockBatteryEntry4).getConsumedPowerInBackground();
doReturn(0.1).when(mMockBatteryEntry4).getConsumedPowerInCached();
doReturn(10L).when(mMockBatteryEntry4).getTimeInForegroundMs();
- doReturn(15L).when(mMockBatteryEntry4).getTimeInForegroundServiceMs();
doReturn(10L).when(mMockBatteryEntry4).getTimeInBackgroundMs();
doReturn(4).when(mMockBatteryEntry4).getUid();
doReturn(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY)
@@ -1179,30 +1188,27 @@
doReturn(BatteryConsumer.POWER_COMPONENT_CAMERA)
.when(mMockBatteryEntry4).getPowerComponentId();
- final BatteryDiffData batteryDiffData = DataProcessor.generateBatteryDiffData(
- mContext, batteryEntryList, mBatteryUsageStats);
+ final BatteryDiffData batteryDiffData = DataProcessor.generateBatteryDiffData(mContext,
+ DataProcessor.convertToBatteryHistEntry(batteryEntryList, mBatteryUsageStats));
assertBatteryDiffEntry(
batteryDiffData.getAppDiffEntryList().get(0), 0, /*uid=*/ 2L,
- ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 25.0,
+ ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 100.0,
/*foregroundUsageConsumePower=*/ 0.5, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
- /*foregroundUsageTimeInMs=*/ 20, /*foregroundServiceUsageTimeInMs=*/ 30,
- /*backgroundUsageTimeInMs=*/ 20);
+ /*foregroundUsageTimeInMs=*/ 20, /*backgroundUsageTimeInMs=*/ 20);
assertBatteryDiffEntry(
batteryDiffData.getAppDiffEntryList().get(1), 0, /*uid=*/ 1L,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 0.0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
- /*foregroundUsageTimeInMs=*/ 30, /*foregroundServiceUsageTimeInMs=*/ 20,
- /*backgroundUsageTimeInMs=*/ 40);
+ /*foregroundUsageTimeInMs=*/ 30, /*backgroundUsageTimeInMs=*/ 40);
assertBatteryDiffEntry(
batteryDiffData.getSystemDiffEntryList().get(0), 0, /*uid=*/ 4L,
- ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*consumePercentage=*/ 75.0,
+ ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*consumePercentage=*/ 100.0,
/*foregroundUsageConsumePower=*/ 0.9, /*foregroundServiceUsageConsumePower=*/ 0.2,
/*backgroundUsageConsumePower=*/ 0.3, /*cachedUsageConsumePower=*/ 0.1,
- /*foregroundUsageTimeInMs=*/ 10, /*foregroundServiceUsageTimeInMs=*/ 15,
- /*backgroundUsageTimeInMs=*/ 10);
+ /*foregroundUsageTimeInMs=*/ 10, /*backgroundUsageTimeInMs=*/ 10);
}
private static Map<Long, Map<String, BatteryHistEntry>> createHistoryMap(
@@ -1241,8 +1247,7 @@
final double foregroundServiceUsageConsumePower,
final double backgroundUsageConsumePower, final double cachedUsageConsumePower,
final long uid, final long userId, final int consumerType,
- final long foregroundUsageTimeInMs, final long foregroundServiceUsageTimeInMs,
- final long backgroundUsageTimeInMs) {
+ final long foregroundUsageTimeInMs, final long backgroundUsageTimeInMs) {
// Only insert required fields.
final BatteryInformation batteryInformation =
BatteryInformation
@@ -1254,7 +1259,6 @@
.setBackgroundUsageConsumePower(backgroundUsageConsumePower)
.setCachedUsageConsumePower(cachedUsageConsumePower)
.setForegroundUsageTimeInMs(foregroundUsageTimeInMs)
- .setForegroundServiceUsageTimeInMs(foregroundServiceUsageTimeInMs)
.setBackgroundUsageTimeInMs(backgroundUsageTimeInMs)
.build();
final ContentValues values = new ContentValues();
@@ -1307,16 +1311,15 @@
private static void verifyExpectedTimestampSlots(
final Calendar start,
- final Calendar end,
+ final Calendar current,
final Calendar expectedStart,
final Calendar expectedEnd) {
expectedStart.set(Calendar.MILLISECOND, 0);
expectedEnd.set(Calendar.MILLISECOND, 0);
final ArrayList<Long> timestampSlots = new ArrayList<>();
timestampSlots.add(start.getTimeInMillis());
- timestampSlots.add(end.getTimeInMillis());
final List<Long> resultList =
- DataProcessor.getTimestampSlots(timestampSlots);
+ DataProcessor.getTimestampSlots(timestampSlots, current.getTimeInMillis());
for (int index = 0; index < resultList.size(); index++) {
final long expectedTimestamp =
@@ -1333,8 +1336,7 @@
final double foregroundUsageConsumePower,
final double foregroundServiceUsageConsumePower,
final double backgroundUsageConsumePower, final double cachedUsageConsumePower,
- final long foregroundUsageTimeInMs, final long foregroundServiceUsageTimeInMs,
- final long backgroundUsageTimeInMs) {
+ final long foregroundUsageTimeInMs, final long backgroundUsageTimeInMs) {
assertThat(entry.mBatteryHistEntry.mUserId).isEqualTo(userId);
assertThat(entry.mBatteryHistEntry.mUid).isEqualTo(uid);
assertThat(entry.mBatteryHistEntry.mConsumerType).isEqualTo(consumerType);
@@ -1345,8 +1347,6 @@
assertThat(entry.mBackgroundUsageConsumePower).isEqualTo(backgroundUsageConsumePower);
assertThat(entry.mCachedUsageConsumePower).isEqualTo(cachedUsageConsumePower);
assertThat(entry.mForegroundUsageTimeInMs).isEqualTo(foregroundUsageTimeInMs);
- assertThat(entry.mForegroundServiceUsageTimeInMs)
- .isEqualTo(foregroundServiceUsageTimeInMs);
assertThat(entry.mBackgroundUsageTimeInMs).isEqualTo(backgroundUsageTimeInMs);
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ExpandDividerPreferenceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ExpandDividerPreferenceTest.java
deleted file mode 100644
index e36f948..0000000
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/ExpandDividerPreferenceTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.fuelgauge.batteryusage;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.settings.R;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public final class ExpandDividerPreferenceTest {
-
- private Context mContext;
- private ExpandDividerPreference mExpandDividerPreference;
-
- private ImageView mImageView;
- private TextView mTextView;
-
- @Before
- public void setUp() {
- mContext = spy(RuntimeEnvironment.application);
- mImageView = spy(new ImageView(mContext));
- mTextView = spy(new TextView(mContext));
- mExpandDividerPreference = new ExpandDividerPreference(mContext);
- doReturn(R.id.expand_title).when(mTextView).getId();
- doReturn(R.id.expand_icon).when(mImageView).getId();
- }
-
- @Test
- public void testConstructor_returnExpectedResult() {
- assertThat(mExpandDividerPreference.getKey())
- .isEqualTo(ExpandDividerPreference.PREFERENCE_KEY);
- assertThat(mExpandDividerPreference.getLayoutResource())
- .isEqualTo(R.layout.preference_expand_divider);
- }
-
- @Test
- public void testSetTitle_setTitleContentIntoTextView() {
- final String titleContent = "title content";
- mExpandDividerPreference.mTextView = mTextView;
-
- mExpandDividerPreference.setTitle(titleContent);
-
- verify(mTextView).setText(titleContent);
- }
-
- @Test
- public void testOnClick_switchExpandStateAndInvokeCallback() {
- final boolean[] isExpandedArray = new boolean[]{false};
- mExpandDividerPreference.mImageView = mImageView;
- mExpandDividerPreference.setOnExpandListener(
- isExpanded -> isExpandedArray[0] = isExpanded);
-
- // Click the item first time from false -> true.
- mExpandDividerPreference.onClick();
- // Verifies the first time click result.
- verify(mImageView).setImageResource(R.drawable.ic_settings_expand_less);
- assertThat(isExpandedArray[0]).isTrue();
-
- // Clicks the item second time from true -> false.
- mExpandDividerPreference.onClick();
- // Verifies the second time click result.
- verify(mImageView).setImageResource(R.drawable.ic_settings_expand_more);
- assertThat(isExpandedArray[0]).isFalse();
- }
-
- @Test
- public void testSetIsExpanded_updateStateButNotInvokeCallback() {
- final boolean[] isExpandedArray = new boolean[]{false};
- mExpandDividerPreference.mImageView = mImageView;
- mExpandDividerPreference.setOnExpandListener(
- isExpanded -> isExpandedArray[0] = isExpanded);
-
- mExpandDividerPreference.setIsExpanded(true);
-
- verify(mImageView).setImageResource(R.drawable.ic_settings_expand_less);
- assertThat(isExpandedArray[0]).isFalse();
- }
-}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/TabPreferenceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/TabPreferenceTest.java
new file mode 100644
index 0000000..c106b48
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/TabPreferenceTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.fuelgauge.batteryusage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+
+import androidx.fragment.app.Fragment;
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+
+import com.google.android.material.tabs.TabLayout;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public final class TabPreferenceTest {
+
+ private Context mContext;
+ private TabPreference mTabPreference;
+
+ @Mock
+ private Fragment mMockFragment;
+ @Mock
+ private TabLayout mMockTabLayout;
+
+ private final String[] mTabTitles = new String[]{"tab1", "tab2"};
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ mTabPreference = new TabPreference(mContext, /*attrs=*/ null);
+ }
+
+ @Test
+ public void constructor_returnExpectedResult() {
+ assertThat(mTabPreference.getLayoutResource()).isEqualTo(R.layout.preference_tab);
+ }
+
+ @Test
+ public void initializeTabs_returnExpectedResult() {
+ mTabPreference.initializeTabs(mMockFragment, mTabTitles);
+ assertThat(mTabPreference.mTabTitles).isEqualTo(mTabTitles);
+ }
+
+ @Test
+ public void onSaveInstanceState_returnExpectedResult() {
+ doReturn(1).when(mMockTabLayout).getSelectedTabPosition();
+ mTabPreference.mTabLayout = mMockTabLayout;
+ TabPreference.SavedState savedState =
+ (TabPreference.SavedState) mTabPreference.onSaveInstanceState();
+ assertThat(savedState.getTabPosition()).isEqualTo(1);
+ }
+
+ @Test
+ public void onRestoreInstanceState_returnExpectedResult() {
+ TabPreference.SavedState savedState =
+ new TabPreference.SavedState(Preference.BaseSavedState.EMPTY_STATE, 2);
+ mTabPreference.onRestoreInstanceState(savedState);
+ assertThat(mTabPreference.mSavedTabPosition).isEqualTo(2);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateTest.java
index 002e4fd..9b9003e 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/db/BatteryStateTest.java
@@ -63,7 +63,6 @@
.setPercentOfTotal(10)
.setDrainType(1)
.setForegroundUsageTimeInMs(60000)
- .setForegroundServiceUsageTimeInMs(30000)
.setBackgroundUsageTimeInMs(10000)
.build();
}
diff --git a/tests/robotests/src/com/android/settings/network/BluetoothWiFiResetPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/BluetoothWiFiResetPreferenceControllerTest.java
new file mode 100644
index 0000000..3aea4a8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/BluetoothWiFiResetPreferenceControllerTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.network;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.ConnectivityManager;
+import android.os.UserManager;
+import android.telephony.TelephonyManager;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowToast;
+
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothWiFiResetPreferenceControllerTest {
+
+ private static final String PREFERENCE_KEY = "network_reset_bluetooth_wifi_pref";
+
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private ConnectivityManager mConnectivityManager;
+ @Mock
+ private TelephonyManager mTelephonyManager;
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getResources()).thenReturn(mResources);
+
+ mockService(Context.CONNECTIVITY_SERVICE, ConnectivityManager.class,
+ mConnectivityManager);
+ mockService(Context.TELEPHONY_SERVICE, TelephonyManager.class, mTelephonyManager);
+ }
+
+ @Test
+ public void getAvailabilityStatus_returnAvailable_asOwnerUser() {
+ mockService(Context.USER_SERVICE, UserManager.class, mUserManager);
+ doReturn(true).when(mUserManager).isAdminUser();
+
+ BluetoothWiFiResetPreferenceController target =
+ new BluetoothWiFiResetPreferenceController(mContext, PREFERENCE_KEY);
+
+ assertThat(target.getAvailabilityStatus()).isEqualTo(
+ BluetoothWiFiResetPreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void resetOperation_notResetConnectivity_onDeviceWithSimVisible() {
+ mockService(Context.CONNECTIVITY_SERVICE, ConnectivityManager.class,
+ mConnectivityManager);
+ when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(true);
+
+ BluetoothWiFiResetPreferenceController target =
+ new BluetoothWiFiResetPreferenceController(mContext, PREFERENCE_KEY);
+
+ try {
+ target.resetOperation().run();
+ } catch (Exception exception) {}
+ verify(mConnectivityManager, never()).factoryReset();
+ }
+
+ @Test
+ public void endOfReset_toastMessage_whenSuccess() {
+ String testText = "reset_bluetooth_wifi_complete_toast";
+ when(mResources.getString(R.string.reset_bluetooth_wifi_complete_toast)).thenReturn(testText);
+ BluetoothWiFiResetPreferenceController target =
+ new BluetoothWiFiResetPreferenceController(mContext, PREFERENCE_KEY);
+
+ target.endOfReset(null);
+
+ assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(testText);
+ }
+
+ private <T> void mockService(String serviceName, Class<T> serviceClass, T service) {
+ when(mContext.getSystemServiceName(serviceClass)).thenReturn(serviceName);
+ when(mContext.getSystemService(serviceName)).thenReturn(service);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java
index 2d023d7..251b1d7 100644
--- a/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java
@@ -114,6 +114,7 @@
@Test
public void isSupportEndItem_withBleDevice_returnsTrue() {
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
+ doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
assertThat(mController.isSupportEndItem()).isTrue();
@@ -130,14 +131,35 @@
@Test
public void isSupportEndItem_withNonBleDevice_returnsFalse() {
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
+ doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
doReturn(mDevice2).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
assertThat(mController.isSupportEndItem()).isFalse();
}
@Test
+ public void isSupportEndItem_deviceIsBroadcastingAndConnectedToNonBleDevice_returnsTrue() {
+ doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
+ doReturn(true).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
+ doReturn(mDevice2).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
+
+ assertThat(mController.isSupportEndItem()).isTrue();
+ }
+
+ @Test
+ public void isSupportEndItem_deviceIsNotBroadcastingAndConnectedToNonBleDevice_returnsFalse() {
+ doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
+ doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
+ doReturn(mDevice2).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
+
+ assertThat(mController.isSupportEndItem()).isFalse();
+ }
+
+
+ @Test
public void getSliceEndItem_NotSupportEndItem_getsNullSliceAction() {
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
+ doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
doReturn(mDevice2).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
final SliceAction sliceAction = mController.getSliceEndItem(mContext);
diff --git a/tests/robotests/src/com/android/settings/security/MemtagHelperTest.java b/tests/robotests/src/com/android/settings/security/MemtagHelperTest.java
index 207fa61..2b9ecf7 100644
--- a/tests/robotests/src/com/android/settings/security/MemtagHelperTest.java
+++ b/tests/robotests/src/com/android/settings/security/MemtagHelperTest.java
@@ -87,6 +87,14 @@
}
@Test
+ public void getAvailabilityStatus_isForcedOn_isDISABLED_DEPENDENT_SETTING() {
+ ShadowSystemProperties.override(mDeviceConfigOverride, "force_on");
+ ShadowSystemProperties.override(mMemtagSupportedProperty, "true");
+ assertThat(MemtagHelper.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+ }
+
+ @Test
public void getAvailabilityStatus_isUnsupported_isUNSUPPORTED_ON_DEVICE() {
ShadowSystemProperties.override(mDeviceConfigOverride, "");
ShadowSystemProperties.override(mMemtagSupportedProperty, "false");
@@ -159,4 +167,13 @@
ShadowSystemProperties.override(mMemtagProperty, "memtag");
assertThat(MemtagHelper.getSummary()).isEqualTo(R.string.memtag_force_off);
}
+
+ @Test
+ @Config(shadows = {ZygoteShadow.class})
+ public void getSummary_forceOffOverride_memtag_force_on() {
+ ZygoteShadow.setSupportsMemoryTagging(false);
+ ShadowSystemProperties.override(mDeviceConfigOverride, "force_on");
+ ShadowSystemProperties.override(mMemtagProperty, "memtag");
+ assertThat(MemtagHelper.getSummary()).isEqualTo(R.string.memtag_force_on);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/spa/app/appinfo/AppPermissionSummaryTest.kt b/tests/robotests/src/com/android/settings/spa/app/appinfo/AppPermissionSummaryTest.kt
deleted file mode 100644
index ce1c1b7..0000000
--- a/tests/robotests/src/com/android/settings/spa/app/appinfo/AppPermissionSummaryTest.kt
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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.spa.app.appinfo
-
-import android.content.Context
-import android.content.pm.ApplicationInfo
-import android.content.pm.PackageManager
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.Observer
-import androidx.test.core.app.ApplicationProvider
-import com.android.settings.R
-import com.android.settingslib.applications.PermissionsSummaryHelper
-import com.android.settingslib.applications.PermissionsSummaryHelper.PermissionsResultCallback
-import com.google.common.truth.Truth.assertThat
-import java.util.concurrent.CountDownLatch
-import java.util.concurrent.TimeUnit
-import java.util.concurrent.TimeoutException
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.any
-import org.mockito.Mockito.doReturn
-import org.mockito.Mockito.eq
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.Spy
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-import org.robolectric.RobolectricTestRunner
-import org.robolectric.annotation.Config
-import org.robolectric.annotation.Implementation
-import org.robolectric.annotation.Implements
-import org.mockito.Mockito.`when` as whenever
-
-@RunWith(RobolectricTestRunner::class)
-@Config(shadows = [ShadowPermissionsSummaryHelper::class])
-class AppPermissionSummaryTest {
-
- @JvmField
- @Rule
- val mockito: MockitoRule = MockitoJUnit.rule()
-
- @Spy
- private var context: Context = ApplicationProvider.getApplicationContext()
-
- @Mock
- private lateinit var packageManager: PackageManager
-
- private lateinit var summaryLiveData: AppPermissionSummaryLiveData
-
- @Before
- fun setUp() {
- doReturn(context).`when`(context).createContextAsUser(any(), eq(0))
- whenever(context.packageManager).thenReturn(packageManager)
-
- val app = ApplicationInfo().apply {
- packageName = PACKAGE_NAME
- }
- summaryLiveData = AppPermissionSummaryLiveData(context, app)
- }
-
- @Test
- fun permissionsChangeListener() {
- summaryLiveData.getOrAwaitValue {
- verify(packageManager).addOnPermissionsChangeListener(any())
- verify(packageManager, never()).removeOnPermissionsChangeListener(any())
- }
- verify(packageManager).removeOnPermissionsChangeListener(any())
- }
-
- @Test
- fun summary_noPermissionsRequested() {
- ShadowPermissionsSummaryHelper.requestedPermissionCount = 0
-
- val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!
-
- assertThat(summary).isEqualTo(
- context.getString(R.string.runtime_permissions_summary_no_permissions_requested)
- )
- assertThat(enabled).isFalse()
- }
-
- @Test
- fun summary_noPermissionsGranted() {
- ShadowPermissionsSummaryHelper.requestedPermissionCount = 1
- ShadowPermissionsSummaryHelper.grantedGroupLabels = emptyList()
-
- val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!
-
- assertThat(summary).isEqualTo(
- context.getString(R.string.runtime_permissions_summary_no_permissions_granted)
- )
- assertThat(enabled).isTrue()
- }
-
- @Test
- fun onPermissionSummaryResult_hasRuntimePermission_shouldSetPermissionAsSummary() {
- ShadowPermissionsSummaryHelper.requestedPermissionCount = 1
- ShadowPermissionsSummaryHelper.grantedGroupLabels = listOf(PERMISSION)
-
- val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!
-
- assertThat(summary).isEqualTo(PERMISSION)
- assertThat(enabled).isTrue()
- }
-
- @Test
- fun onPermissionSummaryResult_hasAdditionalPermission_shouldSetAdditionalSummary() {
- ShadowPermissionsSummaryHelper.requestedPermissionCount = 5
- ShadowPermissionsSummaryHelper.additionalGrantedPermissionCount = 2
- ShadowPermissionsSummaryHelper.grantedGroupLabels = listOf(PERMISSION)
-
- val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!
-
- assertThat(summary).isEqualTo("Storage and 2 additional permissions")
- assertThat(enabled).isTrue()
- }
-
- companion object {
- private const val PACKAGE_NAME = "packageName"
- private const val PERMISSION = "Storage"
- }
-}
-
-@Implements(PermissionsSummaryHelper::class)
-private object ShadowPermissionsSummaryHelper {
- var requestedPermissionCount = 0
- var additionalGrantedPermissionCount = 0
- var grantedGroupLabels: List<CharSequence> = emptyList()
-
- @Implementation
- @JvmStatic
- @Suppress("UNUSED_PARAMETER")
- fun getPermissionSummary(context: Context, pkg: String, callback: PermissionsResultCallback) {
- callback.onPermissionSummaryResult(
- requestedPermissionCount,
- additionalGrantedPermissionCount,
- grantedGroupLabels,
- )
- }
-}
-
-private fun <T> LiveData<T>.getOrAwaitValue(
- time: Long = 2,
- timeUnit: TimeUnit = TimeUnit.SECONDS,
- afterObserve: () -> Unit = {},
-): T? {
- var data: T? = null
- val latch = CountDownLatch(1)
- val observer = Observer<T> { o ->
- data = o
- latch.countDown()
- }
- this.observeForever(observer)
-
- afterObserve()
-
- try {
- // Don't wait indefinitely if the LiveData is not set.
- if (!latch.await(time, timeUnit)) {
- throw TimeoutException("LiveData value was never set.")
- }
-
- } finally {
- this.removeObserver(observer)
- }
-
- return data
-}
diff --git a/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java b/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
index 485caef..f119d6e6 100644
--- a/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
@@ -107,7 +107,6 @@
.setPercentOfTotal(10f)
.setDrainType(1)
.setForegroundUsageTimeInMs(60000)
- .setForegroundServiceUsageTimeInMs(30000)
.setBackgroundUsageTimeInMs(10000)
.setForegroundUsageConsumePower(0.1f)
.setForegroundServiceUsageConsumePower(0.05f)
diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
index 6261db9..386f66d 100644
--- a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java
@@ -16,6 +16,9 @@
package com.android.settings.wifi;
+import static com.android.wifitrackerlib.WifiEntry.SECURITY_PSK;
+import static com.android.wifitrackerlib.WifiEntry.SECURITY_SAE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -47,16 +50,20 @@
import org.junit.Before;
import org.junit.Ignore;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
-import org.mockito.MockitoAnnotations;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
@@ -64,15 +71,34 @@
public class NetworkRequestDialogFragmentTest {
private static final String KEY_SSID = "key_ssid";
- private static final String KEY_SECURITY = "key_security";
+ private static final String TEST_CAPABILITIES_OPEN = "[ESS]";
+ private static final String TEST_CAPABILITIES_WPA2_PSK = "[WPA2-PSK-CCMP][ESS]";
+ private static final String TEST_CAPABILITIES_WPA3_SAE = "[RSN-PSK+SAE-CCMP][ESS]";
private static final String TEST_APP_NAME = "TestAppName";
+ @Rule
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Mock
+ WifiPickerTracker mWifiPickerTracker;
+ @Mock
+ WifiEntry mWifiEntry;
+
private FragmentActivity mActivity;
private NetworkRequestDialogFragment networkRequestDialogFragment;
+ ScanResult mScanResult = new ScanResult();
+
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
+ when(mWifiEntry.getSsid()).thenReturn(KEY_SSID);
+ when(mWifiEntry.getSecurityTypes()).thenReturn(Arrays.asList(SECURITY_PSK, SECURITY_SAE));
+ when(mWifiEntry.getSecurity()).thenReturn(SECURITY_PSK);
+ when(mWifiPickerTracker.getConnectedWifiEntry()).thenReturn(null);
+ when(mWifiPickerTracker.getWifiEntries()).thenReturn(Arrays.asList(mWifiEntry));
+
+ mScanResult.SSID = KEY_SSID;
+ mScanResult.capabilities = TEST_CAPABILITIES_OPEN;
+
FakeFeatureFactory fakeFeatureFactory = FakeFeatureFactory.setupForTest();
when(fakeFeatureFactory.wifiTrackerLibProvider.createWifiPickerTracker(
any(), any(), any(), any(), any(), anyLong(), anyLong(), any()))
@@ -82,7 +108,7 @@
new Intent().putExtra(NetworkRequestDialogFragment.EXTRA_APP_NAME,
TEST_APP_NAME)).setup().get();
networkRequestDialogFragment = spy(NetworkRequestDialogFragment.newInstance());
- networkRequestDialogFragment.mWifiPickerTracker = mock(WifiPickerTracker.class);
+ networkRequestDialogFragment.mWifiPickerTracker = mWifiPickerTracker;
}
@Ignore
@@ -151,12 +177,10 @@
@Test
public void onWifiStateChanged_nonEmptyMatchedScanResults_shouldUpdateWifiEntries() {
final InOrder inOrder = inOrder(networkRequestDialogFragment);
+ mScanResult.capabilities = TEST_CAPABILITIES_OPEN;
+ networkRequestDialogFragment.onMatch(Arrays.asList(mScanResult));
- final List<ScanResult> scanResults = new ArrayList<>();
- networkRequestDialogFragment.mMatchedScanResults = scanResults;
- ScanResult scanResult = mock(ScanResult.class);
- networkRequestDialogFragment.mMatchedScanResults.add(scanResult);
- networkRequestDialogFragment.onMatch(scanResults);
+ networkRequestDialogFragment.onWifiStateChanged();
inOrder.verify(networkRequestDialogFragment).updateWifiEntries();
inOrder.verify(networkRequestDialogFragment).updateUi();
@@ -165,12 +189,10 @@
@Test
public void onWifiEntriesChanged_nonEmptyMatchedScanResults_shouldUpdateWifiEntries() {
final InOrder inOrder = inOrder(networkRequestDialogFragment);
+ mScanResult.capabilities = TEST_CAPABILITIES_OPEN;
+ networkRequestDialogFragment.onMatch(Arrays.asList(mScanResult));
- final List<ScanResult> scanResults = new ArrayList<>();
- networkRequestDialogFragment.mMatchedScanResults = scanResults;
- ScanResult scanResult = mock(ScanResult.class);
- networkRequestDialogFragment.mMatchedScanResults.add(scanResult);
- networkRequestDialogFragment.onMatch(scanResults);
+ networkRequestDialogFragment.onWifiEntriesChanged();
inOrder.verify(networkRequestDialogFragment).updateWifiEntries();
inOrder.verify(networkRequestDialogFragment).updateUi();
@@ -288,4 +310,34 @@
// Check
verify(selectionCallback, times(1)).reject();
}
+
+ @Test
+ public void updateWifiEntries_noMatchSecurityWifi_filteredWifiIsEmpty() {
+ mScanResult.capabilities = TEST_CAPABILITIES_OPEN;
+ networkRequestDialogFragment.onMatch(Arrays.asList(mScanResult));
+
+ networkRequestDialogFragment.updateWifiEntries();
+
+ assertThat(networkRequestDialogFragment.mFilteredWifiEntries.size()).isEqualTo(0);
+ }
+
+ @Test
+ public void updateWifiEntries_matchWpa2Wifi_filteredWifiNotEmpty() {
+ mScanResult.capabilities = TEST_CAPABILITIES_WPA2_PSK;
+ networkRequestDialogFragment.onMatch(Arrays.asList(mScanResult));
+
+ networkRequestDialogFragment.updateWifiEntries();
+
+ assertThat(networkRequestDialogFragment.mFilteredWifiEntries.size()).isNotEqualTo(0);
+ }
+
+ @Test
+ public void updateWifiEntries_matchWpa3Wifi_filteredWifiNotEmpty() {
+ mScanResult.capabilities = TEST_CAPABILITIES_WPA3_SAE;
+ networkRequestDialogFragment.onMatch(Arrays.asList(mScanResult));
+
+ networkRequestDialogFragment.updateWifiEntries();
+
+ assertThat(networkRequestDialogFragment.mFilteredWifiEntries.size()).isNotEqualTo(0);
+ }
}
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/AllAppListTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/AllAppListTest.kt
new file mode 100644
index 0000000..1a5f3ab
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/spa/app/AllAppListTest.kt
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.spa.app
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import androidx.compose.runtime.SideEffect
+import androidx.compose.runtime.State
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performClick
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.R
+import com.android.settingslib.spa.framework.compose.stateOf
+import com.android.settingslib.spa.testutils.FakeNavControllerWrapper
+import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
+import com.android.settingslib.spaprivileged.template.app.AppListInput
+import com.android.settingslib.spaprivileged.template.app.AppListItemModel
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.runTest
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class AllAppListTest {
+ @get:Rule
+ val composeTestRule = createComposeRule()
+
+ private val context: Context = ApplicationProvider.getApplicationContext()
+
+ private val fakeNavControllerWrapper = FakeNavControllerWrapper()
+
+ @Test
+ fun allAppListPageProvider_name() {
+ assertThat(AllAppListPageProvider.name).isEqualTo("AllAppList")
+ }
+
+ @Test
+ fun injectEntry_title() {
+ setInjectEntry()
+
+ composeTestRule.onNodeWithText(context.getString(R.string.all_apps)).assertIsDisplayed()
+ }
+
+ @Test
+ fun injectEntry_onClick_navigate() {
+ setInjectEntry()
+
+ composeTestRule.onNodeWithText(context.getString(R.string.all_apps)).performClick()
+
+ assertThat(fakeNavControllerWrapper.navigateCalledWith).isEqualTo("AllAppList")
+ }
+
+ private fun setInjectEntry() {
+ composeTestRule.setContent {
+ fakeNavControllerWrapper.Wrapper {
+ AllAppListPageProvider.buildInjectEntry().build().UiLayout()
+ }
+ }
+ }
+
+ @Test
+ fun title_displayed() {
+ composeTestRule.setContent {
+ AllAppListPage {}
+ }
+
+ composeTestRule.onNodeWithText(context.getString(R.string.all_apps)).assertIsDisplayed()
+ }
+
+ @Test
+ fun showInstantApps_isTrue() {
+ val input = getAppListInput()
+
+ assertThat(input.config.showInstantApps).isTrue()
+ }
+
+ @Test
+ fun item_labelDisplayed() {
+ setItemContent()
+
+ composeTestRule.onNodeWithText(LABEL).assertIsDisplayed()
+ }
+
+ @Test
+ fun item_summaryDisplayed() {
+ setItemContent()
+
+ composeTestRule.onNodeWithText(SUMMARY).assertIsDisplayed()
+ }
+
+ @Test
+ fun item_onClick_navigate() {
+ setItemContent()
+
+ composeTestRule.onNodeWithText(LABEL).performClick()
+
+ assertThat(fakeNavControllerWrapper.navigateCalledWith)
+ .isEqualTo("AppInfoSettings/package.name/0")
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ fun allAppListModel_transform() = runTest {
+ val listModel = AllAppListModel { stateOf(SUMMARY) }
+
+ val recordListFlow = listModel.transform(flowOf(USER_ID), flowOf(listOf(APP)))
+
+ val recordList = recordListFlow.firstWithTimeoutOrNull()!!
+ assertThat(recordList).hasSize(1)
+ assertThat(recordList[0].app).isSameInstanceAs(APP)
+ }
+
+ @Test
+ fun allAppListModel_getSummary() {
+ val listModel = AllAppListModel { stateOf(SUMMARY) }
+
+ lateinit var summaryState: State<String>
+ composeTestRule.setContent {
+ summaryState = listModel.getSummary(option = 0, record = AppRecordWithSize(app = APP))
+ }
+
+ assertThat(summaryState.value).isEqualTo(SUMMARY)
+ }
+
+ private fun getAppListInput(): AppListInput<AppRecordWithSize> {
+ lateinit var input: AppListInput<AppRecordWithSize>
+ composeTestRule.setContent {
+ AllAppListPage {
+ SideEffect {
+ input = this
+ }
+ }
+ }
+ return input
+ }
+
+ private fun setItemContent() {
+ composeTestRule.setContent {
+ AllAppListPage {
+ fakeNavControllerWrapper.Wrapper {
+ AppListItemModel(
+ record = AppRecordWithSize(app = APP),
+ label = LABEL,
+ summary = stateOf(SUMMARY),
+ ).appItem()
+ }
+ }
+ }
+ }
+
+ private companion object {
+ const val USER_ID = 0
+ const val PACKAGE_NAME = "package.name"
+ const val LABEL = "Label"
+ const val SUMMARY = "Summary"
+ val APP = ApplicationInfo().apply {
+ packageName = PACKAGE_NAME
+ }
+ }
+}
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/ResetAppPreferencesTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/ResetAppPreferencesTest.kt
index b144ad6..ffd5831 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/ResetAppPreferencesTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/ResetAppPreferencesTest.kt
@@ -28,14 +28,12 @@
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Spy
@RunWith(AndroidJUnit4::class)
class ResetAppPreferencesTest {
@get:Rule
val composeTestRule = createComposeRule()
- @Spy
private val context: Context = ApplicationProvider.getApplicationContext()
@Test
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppLocalePreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppLocalePreferenceTest.kt
index 39524df..82c9ee9 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppLocalePreferenceTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppLocalePreferenceTest.kt
@@ -22,11 +22,9 @@
import android.content.pm.PackageManager
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick
import androidx.test.core.app.ApplicationProvider
@@ -47,7 +45,6 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers
import org.mockito.Mock
import org.mockito.Mockito.any
import org.mockito.Mockito.doNothing
@@ -80,9 +77,8 @@
.strictness(Strictness.LENIENT)
.startMocking()
whenever(context.packageManager).thenReturn(packageManager)
- whenever(AppLocaleUtil.canDisplayLocaleUi(any(), ArgumentMatchers.eq(APP), any()))
- .thenReturn(true)
- whenever(AppLocaleDetails.getSummary(any(), ArgumentMatchers.eq(APP))).thenReturn(SUMMARY)
+ whenever(AppLocaleUtil.canDisplayLocaleUi(any(), eq(APP), any())).thenReturn(true)
+ whenever(AppLocaleDetails.getSummary(any(), eq(APP))).thenReturn(SUMMARY)
}
@After
@@ -92,8 +88,7 @@
@Test
fun whenCanNotDisplayLocalUi_notDisplayed() {
- whenever(AppLocaleUtil.canDisplayLocaleUi(any(), ArgumentMatchers.eq(APP), any()))
- .thenReturn(false)
+ whenever(AppLocaleUtil.canDisplayLocaleUi(any(), eq(APP), any())).thenReturn(false)
setContent()
@@ -104,8 +99,9 @@
fun whenCanDisplayLocalUi_displayed() {
setContent()
- composeTestRule.onNodeWithText(context.getString(R.string.app_locale_preference_title))
- .assertIsDisplayed()
+ composeTestRule.waitUntilExists(
+ hasText(context.getString(R.string.app_locale_preference_title))
+ )
composeTestRule.waitUntilExists(hasText(SUMMARY))
}
@@ -131,10 +127,11 @@
AppLocalePreference(APP)
}
}
+ composeTestRule.delay()
}
private companion object {
- const val PACKAGE_NAME = "packageName"
+ const val PACKAGE_NAME = "package.name"
const val UID = 123
val APP = ApplicationInfo().apply {
packageName = PACKAGE_NAME
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppPermissionSummaryTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppPermissionSummaryTest.kt
new file mode 100644
index 0000000..c82da1a
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppPermissionSummaryTest.kt
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.spa.app.appinfo
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
+import com.android.settings.R
+import com.android.settings.testutils.mockAsUser
+import com.android.settingslib.applications.PermissionsSummaryHelper
+import com.android.settingslib.applications.PermissionsSummaryHelper.PermissionsResultCallback
+import com.android.settingslib.spa.testutils.getOrAwaitValue
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.eq
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoSession
+import org.mockito.Spy
+import org.mockito.quality.Strictness
+import org.mockito.Mockito.`when` as whenever
+
+@RunWith(AndroidJUnit4::class)
+class AppPermissionSummaryTest {
+ @get:Rule
+ val instantTaskExecutorRule = InstantTaskExecutorRule()
+
+ private lateinit var mockSession: MockitoSession
+
+ @Spy
+ private var context: Context = ApplicationProvider.getApplicationContext()
+
+ @Mock
+ private lateinit var packageManager: PackageManager
+
+ private lateinit var summaryLiveData: AppPermissionSummaryLiveData
+
+ @Before
+ fun setUp() {
+ mockSession = mockitoSession()
+ .initMocks(this)
+ .mockStatic(PermissionsSummaryHelper::class.java)
+ .strictness(Strictness.LENIENT)
+ .startMocking()
+ context.mockAsUser()
+ whenever(context.packageManager).thenReturn(packageManager)
+
+ summaryLiveData = AppPermissionSummaryLiveData(context, APP)
+ }
+
+ private fun mockGetPermissionSummary(
+ requestedPermissionCount: Int = 0,
+ additionalGrantedPermissionCount: Int = 0,
+ grantedGroupLabels: List<CharSequence> = emptyList(),
+ ) {
+ whenever(PermissionsSummaryHelper.getPermissionSummary(any(), eq(PACKAGE_NAME), any()))
+ .thenAnswer {
+ val callback = it.arguments[2] as PermissionsResultCallback
+ callback.onPermissionSummaryResult(
+ requestedPermissionCount,
+ additionalGrantedPermissionCount,
+ grantedGroupLabels,
+ )
+ }
+ }
+
+ @After
+ fun tearDown() {
+ mockSession.finishMocking()
+ }
+
+ @Test
+ fun permissionsChangeListener() {
+ mockGetPermissionSummary()
+
+ summaryLiveData.getOrAwaitValue {
+ verify(packageManager).addOnPermissionsChangeListener(any())
+ verify(packageManager, never()).removeOnPermissionsChangeListener(any())
+ }
+
+ verify(packageManager).removeOnPermissionsChangeListener(any())
+ }
+
+ @Test
+ fun summary_noPermissionsRequested() {
+ mockGetPermissionSummary(requestedPermissionCount = 0)
+
+ val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!
+
+ assertThat(summary).isEqualTo(
+ context.getString(R.string.runtime_permissions_summary_no_permissions_requested)
+ )
+ assertThat(enabled).isFalse()
+ }
+
+ @Test
+ fun summary_noPermissionsGranted() {
+ mockGetPermissionSummary(requestedPermissionCount = 1, grantedGroupLabels = emptyList())
+
+ val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!
+
+ assertThat(summary).isEqualTo(
+ context.getString(R.string.runtime_permissions_summary_no_permissions_granted)
+ )
+ assertThat(enabled).isTrue()
+ }
+
+ @Test
+ fun onPermissionSummaryResult_hasRuntimePermission_shouldSetPermissionAsSummary() {
+ mockGetPermissionSummary(
+ requestedPermissionCount = 1,
+ grantedGroupLabels = listOf(PERMISSION),
+ )
+
+ val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!
+
+ assertThat(summary).isEqualTo(PERMISSION)
+ assertThat(enabled).isTrue()
+ }
+
+ @Test
+ fun onPermissionSummaryResult_hasAdditionalPermission_shouldSetAdditionalSummary() {
+ mockGetPermissionSummary(
+ requestedPermissionCount = 5,
+ additionalGrantedPermissionCount = 2,
+ grantedGroupLabels = listOf(PERMISSION),
+ )
+
+ val (summary, enabled) = summaryLiveData.getOrAwaitValue()!!
+
+ assertThat(summary).isEqualTo("Storage and 2 additional permissions")
+ assertThat(enabled).isTrue()
+ }
+
+ private companion object {
+ const val PACKAGE_NAME = "packageName"
+ const val PERMISSION = "Storage"
+ val APP = ApplicationInfo().apply {
+ packageName = PACKAGE_NAME
+ }
+ }
+}
diff --git a/tests/unit/src/com/android/settings/deviceinfo/simstatus/SlotSimStatusTest.java b/tests/unit/src/com/android/settings/deviceinfo/simstatus/SlotSimStatusTest.java
new file mode 100644
index 0000000..4c17d15
--- /dev/null
+++ b/tests/unit/src/com/android/settings/deviceinfo/simstatus/SlotSimStatusTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.deviceinfo.simstatus;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.telephony.TelephonyManager;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.concurrent.Executor;
+
+@RunWith(AndroidJUnit4.class)
+public class SlotSimStatusTest {
+
+ @Mock
+ private TelephonyManager mTelephonyManager;
+ @Mock
+ private Executor mExecutor;
+ @Captor
+ private ArgumentCaptor<Runnable> mRunnableCaptor;
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ mockService(Context.TELEPHONY_SERVICE, TelephonyManager.class, mTelephonyManager);
+ }
+
+ @Test
+ public void size_returnNumberOfPhone_whenQuery() {
+ doReturn(2).when(mTelephonyManager).getPhoneCount();
+
+ SlotSimStatus target = new SlotSimStatus(mContext);
+
+ assertEquals(new Integer(target.size()), new Integer(2));
+ }
+
+ @Test
+ public void size_returnNumberOfPhone_whenQueryInBackgroundThread() {
+ doReturn(2).when(mTelephonyManager).getPhoneCount();
+
+ SlotSimStatus target = new SlotSimStatus(mContext, mExecutor);
+
+ verify(mExecutor).execute(mRunnableCaptor.capture());
+ mRunnableCaptor.getValue().run();
+
+ assertEquals(new Integer(target.size()), new Integer(2));
+ }
+
+ @Test
+ public void getPreferenceOrdering_returnOrdering_whenQuery() {
+ doReturn(2).when(mTelephonyManager).getPhoneCount();
+
+ SlotSimStatus target = new SlotSimStatus(mContext);
+ target.setBasePreferenceOrdering(30);
+
+ assertEquals(new Integer(target.getPreferenceOrdering(1)), new Integer(32));
+ }
+
+ @Test
+ public void getPreferenceKey_returnKey_whenQuery() {
+ doReturn(2).when(mTelephonyManager).getPhoneCount();
+
+ SlotSimStatus target = new SlotSimStatus(mContext);
+ target.setBasePreferenceOrdering(50);
+
+ assertEquals(target.getPreferenceKey(1), "sim_status52");
+ }
+
+ private <T> void mockService(String serviceName, Class<T> serviceClass, T service) {
+ when(mContext.getSystemServiceName(serviceClass)).thenReturn(serviceName);
+ when(mContext.getSystemService(serviceName)).thenReturn(service);
+ }
+}