Snap for 11828632 from 619af9349d to 24Q3-release
Change-Id: Id9c908477673ed3cd3c6a6bded87c9a7beef2f88
This commit is contained in:
@@ -2551,9 +2551,9 @@
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
|
||||
android:value="com.android.settings.accessibility.ColorContrastFragment" />
|
||||
android:value="com.android.settings.display.ColorContrastFragment" />
|
||||
<meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
|
||||
android:value="@string/menu_key_accessibility"/>
|
||||
android:value="@string/menu_key_display"/>
|
||||
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
|
||||
android:value="true" />
|
||||
</activity>
|
||||
@@ -3343,6 +3343,7 @@
|
||||
<action android:name="com.google.android.setupwizard.SETUP_WIZARD_FINISHED"/>
|
||||
<action android:name="com.android.settings.battery.action.PERIODIC_JOB_RECHECK"/>
|
||||
<action android:name="android.intent.action.TIME_SET"/>
|
||||
<action android:name="android.intent.action.TIMEZONE_CHANGED"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
@@ -5138,8 +5139,6 @@
|
||||
<action android:name="com.android.settings.action.OPEN_PRIVATE_SPACE_SETTINGS" />
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
|
||||
android:value="@string/menu_key_security"/>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".privatespace.PrivateProfileContextHelperActivity" android:exported="false"/>
|
||||
|
||||
@@ -45,6 +45,7 @@ message BatteryUsageHistoricalLogEntry {
|
||||
FETCH_USAGE_DATA = 4;
|
||||
INSERT_USAGE_DATA = 5;
|
||||
TIME_UPDATED = 6;
|
||||
TIMEZONE_UPDATED = 7;
|
||||
}
|
||||
|
||||
optional int64 timestamp = 1;
|
||||
|
||||
25
res/drawable-sw600dp/ic_settings_about_device_filled.xml
Normal file
25
res/drawable-sw600dp/ic_settings_about_device_filled.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M200,920Q167,920 143.5,896.5Q120,873 120,840L120,120Q120,87 143.5,63.5Q167,40 200,40L760,40Q793,40 816.5,63.5Q840,87 840,120L840,840Q840,873 816.5,896.5Q793,920 760,920L200,920ZM400,800L560,800L560,760L400,760L400,800ZM200,640L760,640L760,240L200,240L200,640Z"/>
|
||||
</vector>
|
||||
29
res/drawable/homepage_highlighted_item_background_v2.xml
Normal file
29
res/drawable/homepage_highlighted_item_background_v2.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="@*android:color/ripple_material_light">
|
||||
<item
|
||||
android:left="?android:attr/listPreferredItemPaddingStart"
|
||||
android:right="?android:attr/listPreferredItemPaddingEnd">
|
||||
<shape android:shape="rectangle">
|
||||
<solid
|
||||
android:color="@color/settingslib_materialColorPrimaryContainer" />
|
||||
<corners
|
||||
android:radius="?android:attr/dialogCornerRadius" />
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
||||
29
res/drawable/homepage_selectable_item_background_v2.xml
Normal file
29
res/drawable/homepage_selectable_item_background_v2.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="?android:attr/colorControlHighlight">
|
||||
<item android:id="@android:id/mask"
|
||||
android:left="?android:attr/listPreferredItemPaddingStart"
|
||||
android:right="?android:attr/listPreferredItemPaddingEnd">
|
||||
<shape android:shape="rectangle">
|
||||
<solid
|
||||
android:color="@android:color/white" />
|
||||
<corners
|
||||
android:radius="?android:attr/dialogCornerRadius" />
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
||||
25
res/drawable/ic_apps_filled.xml
Normal file
25
res/drawable/ic_apps_filled.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M240,800Q207,800 183.5,776.5Q160,753 160,720Q160,687 183.5,663.5Q207,640 240,640Q273,640 296.5,663.5Q320,687 320,720Q320,753 296.5,776.5Q273,800 240,800ZM480,800Q447,800 423.5,776.5Q400,753 400,720Q400,687 423.5,663.5Q447,640 480,640Q513,640 536.5,663.5Q560,687 560,720Q560,753 536.5,776.5Q513,800 480,800ZM720,800Q687,800 663.5,776.5Q640,753 640,720Q640,687 663.5,663.5Q687,640 720,640Q753,640 776.5,663.5Q800,687 800,720Q800,753 776.5,776.5Q753,800 720,800ZM240,560Q207,560 183.5,536.5Q160,513 160,480Q160,447 183.5,423.5Q207,400 240,400Q273,400 296.5,423.5Q320,447 320,480Q320,513 296.5,536.5Q273,560 240,560ZM480,560Q447,560 423.5,536.5Q400,513 400,480Q400,447 423.5,423.5Q447,400 480,400Q513,400 536.5,423.5Q560,447 560,480Q560,513 536.5,536.5Q513,560 480,560ZM720,560Q687,560 663.5,536.5Q640,513 640,480Q640,447 663.5,423.5Q687,400 720,400Q753,400 776.5,423.5Q800,447 800,480Q800,513 776.5,536.5Q753,560 720,560ZM240,320Q207,320 183.5,296.5Q160,273 160,240Q160,207 183.5,183.5Q207,160 240,160Q273,160 296.5,183.5Q320,207 320,240Q320,273 296.5,296.5Q273,320 240,320ZM480,320Q447,320 423.5,296.5Q400,273 400,240Q400,207 423.5,183.5Q447,160 480,160Q513,160 536.5,183.5Q560,207 560,240Q560,273 536.5,296.5Q513,320 480,320ZM720,320Q687,320 663.5,296.5Q640,273 640,240Q640,207 663.5,183.5Q687,160 720,160Q753,160 776.5,183.5Q800,207 800,240Q800,273 776.5,296.5Q753,320 720,320Z"/>
|
||||
</vector>
|
||||
@@ -1,35 +0,0 @@
|
||||
<!--
|
||||
~ Copyright (C) 2024 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<com.android.settingslib.widget.AdaptiveIconShapeDrawable
|
||||
android:width="@dimen/accessibility_icon_size"
|
||||
android:height="@dimen/accessibility_icon_size"
|
||||
android:color="@color/accessibility_feature_background"/>
|
||||
</item>
|
||||
<item android:gravity="center">
|
||||
<vector
|
||||
android:width="@dimen/accessibility_icon_foreground_size"
|
||||
android:height="@dimen/accessibility_icon_foreground_size"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#ffffff"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.48 10,-10S17.52,2 12,2zM11,19.93C7.06,19.44 4,16.08 4,12s3.05,-7.44 7,-7.93V19.93zM13,4.07C14.03,4.2 15,4.52 15.87,5H13V4.07zM13,7h5.24c0.25,0.31 0.48,0.65 0.68,1H13V7zM13,10h6.74c0.08,0.33 0.15,0.66 0.19,1H13V10zM13,19.93V19h2.87C15,19.48 14.03,19.8 13,19.93zM18.24,17H13v-1h5.92C18.72,16.35 18.49,16.69 18.24,17zM19.74,14H13v-1h6.93C19.89,13.34 19.82,13.67 19.74,14z"/>
|
||||
</vector>
|
||||
</item>
|
||||
</layer-list>
|
||||
28
res/drawable/ic_devices_other_filled.xml
Normal file
28
res/drawable/ic_devices_other_filled.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal"
|
||||
android:autoMirrored="true">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M280,800L160,800Q127,800 103.5,776.5Q80,753 80,720L80,240Q80,207 103.5,183.5Q127,160 160,160L800,160L800,240L160,240Q160,240 160,240Q160,240 160,240L160,720Q160,720 160,720Q160,720 160,720L280,720L280,800ZM440,700Q465,700 482.5,682.5Q500,665 500,640Q500,615 482.5,597.5Q465,580 440,580Q415,580 397.5,597.5Q380,615 380,640Q380,665 397.5,682.5Q415,700 440,700ZM360,800L360,729Q341,712 330.5,689Q320,666 320,640Q320,614 330.5,591Q341,568 360,551L360,480L520,480L520,551Q539,568 549.5,591Q560,614 560,640Q560,666 549.5,689Q539,712 520,729L520,800L360,800ZM840,800L640,800Q623,800 611.5,788.5Q600,777 600,760L600,400Q600,383 611.5,371.5Q623,360 640,360L840,360Q857,360 868.5,371.5Q880,383 880,400L880,760Q880,777 868.5,788.5Q857,800 840,800Z"/>
|
||||
</vector>
|
||||
26
res/drawable/ic_help_filled.xml
Normal file
26
res/drawable/ic_help_filled.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal"
|
||||
android:autoMirrored="true">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M478,720Q499,720 513.5,705.5Q528,691 528,670Q528,649 513.5,634.5Q499,620 478,620Q457,620 442.5,634.5Q428,649 428,670Q428,691 442.5,705.5Q457,720 478,720ZM442,566L516,566Q516,533 523.5,514Q531,495 566,462Q592,436 607,412.5Q622,389 622,356Q622,300 581,270Q540,240 484,240Q427,240 391.5,270Q356,300 342,342L408,368Q413,350 430.5,329Q448,308 484,308Q516,308 532,325.5Q548,343 548,364Q548,384 536,401.5Q524,419 506,434Q462,473 452,493Q442,513 442,566ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880Z"/>
|
||||
</vector>
|
||||
26
res/drawable/ic_notifications_filled.xml
Normal file
26
res/drawable/ic_notifications_filled.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M160,760L160,680L240,680L240,400Q240,317 290,252.5Q340,188 420,168L420,140Q420,115 437.5,97.5Q455,80 480,80Q505,80 522.5,97.5Q540,115 540,140L540,168Q620,188 670,252.5Q720,317 720,400L720,680L800,680L800,760L160,760ZM480,880Q447,880 423.5,856.5Q400,833 400,800L560,800Q560,833 536.5,856.5Q513,880 480,880Z"/>
|
||||
</vector>
|
||||
|
||||
25
res/drawable/ic_settings_about_device_filled.xml
Normal file
25
res/drawable/ic_settings_about_device_filled.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M440,660L440,440L520,440L520,660L440,660ZM480,360Q463,360 451.5,348.5Q440,337 440,320Q440,303 451.5,291.5Q463,280 480,280Q497,280 508.5,291.5Q520,303 520,320Q520,337 508.5,348.5Q497,360 480,360ZM280,920Q247,920 223.5,896.5Q200,873 200,840L200,120Q200,87 223.5,63.5Q247,40 280,40L680,40Q713,40 736.5,63.5Q760,87 760,120L760,840Q760,873 736.5,896.5Q713,920 680,920L280,920ZM280,720L680,720L680,240L280,240L280,720Z"/>
|
||||
</vector>
|
||||
25
res/drawable/ic_settings_accessibility_filled.xml
Normal file
25
res/drawable/ic_settings_accessibility_filled.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,160Q447,160 423.5,136.5Q400,113 400,80Q400,47 423.5,23.5Q447,0 480,0Q513,0 536.5,23.5Q560,47 560,80Q560,113 536.5,136.5Q513,160 480,160ZM360,760L360,280Q300,275 238,265Q176,255 120,240L140,160Q218,181 306,190.5Q394,200 480,200Q566,200 654,190.5Q742,181 820,160L840,240Q784,255 722,265Q660,275 600,280L600,760L520,760L520,520L440,520L440,760L360,760ZM320,960Q303,960 291.5,948.5Q280,937 280,920Q280,903 291.5,891.5Q303,880 320,880Q337,880 348.5,891.5Q360,903 360,920Q360,937 348.5,948.5Q337,960 320,960ZM480,960Q463,960 451.5,948.5Q440,937 440,920Q440,903 451.5,891.5Q463,880 480,880Q497,880 508.5,891.5Q520,903 520,920Q520,937 508.5,948.5Q497,960 480,960ZM640,960Q623,960 611.5,948.5Q600,937 600,920Q600,903 611.5,891.5Q623,880 640,880Q657,880 668.5,891.5Q680,903 680,920Q680,937 668.5,948.5Q657,960 640,960Z"/>
|
||||
</vector>
|
||||
25
res/drawable/ic_settings_battery_filled.xml
Normal file
25
res/drawable/ic_settings_battery_filled.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M320,880Q303,880 291.5,868.5Q280,857 280,840L280,200Q280,183 291.5,171.5Q303,160 320,160L400,160L400,80L560,80L560,160L640,160Q657,160 668.5,171.5Q680,183 680,200L680,840Q680,857 668.5,868.5Q657,880 640,880L320,880Z"/>
|
||||
</vector>
|
||||
25
res/drawable/ic_settings_display_filled.xml
Normal file
25
res/drawable/ic_settings_display_filled.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,932L346,800L160,800L160,614L28,480L160,346L160,160L346,160L480,28L614,160L800,160L800,346L932,480L800,614L800,800L614,800L480,932ZM480,820L580,720L720,720L720,580L820,480L720,380L720,240L580,240L480,140L380,240L240,240L240,380L140,480L240,580L240,720L380,720L480,820ZM480,680Q563,680 621.5,621.5Q680,563 680,480Q680,397 621.5,338.5Q563,280 480,280L480,680Z"/>
|
||||
</vector>
|
||||
25
res/drawable/ic_settings_emergency_filled.xml
Normal file
25
res/drawable/ic_settings_emergency_filled.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M410,840L410,602L204,721L134,600L340,480L134,361L204,240L410,359L410,120L550,120L550,359L756,240L826,361L620,480L826,600L756,721L550,602L550,840L410,840Z"/>
|
||||
</vector>
|
||||
25
res/drawable/ic_settings_location_filled.xml
Normal file
25
res/drawable/ic_settings_location_filled.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,480Q513,480 536.5,456.5Q560,433 560,400Q560,367 536.5,343.5Q513,320 480,320Q447,320 423.5,343.5Q400,367 400,400Q400,433 423.5,456.5Q447,480 480,480ZM480,880Q319,743 239.5,625.5Q160,508 160,408Q160,258 256.5,169Q353,80 480,80Q607,80 703.5,169Q800,258 800,408Q800,508 720.5,625.5Q641,743 480,880Z"/>
|
||||
</vector>
|
||||
25
res/drawable/ic_settings_passwords_filled.xml
Normal file
25
res/drawable/ic_settings_passwords_filled.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M280,600Q330,600 365,565Q400,530 400,480Q400,430 365,395Q330,360 280,360Q230,360 195,395Q160,430 160,480Q160,530 195,565Q230,600 280,600ZM280,720Q180,720 110,650Q40,580 40,480Q40,380 110,310Q180,240 280,240Q361,240 421.5,286Q482,332 506,400L841,400L920,479L780,639L680,560L600,640L520,560L506,560Q481,632 419,676Q357,720 280,720Z"/>
|
||||
</vector>
|
||||
25
res/drawable/ic_settings_privacy_filled.xml
Normal file
25
res/drawable/ic_settings_privacy_filled.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,568Q435,568 403.5,536.5Q372,505 372,460Q372,415 403.5,383.5Q435,352 480,352Q525,352 556.5,383.5Q588,415 588,460Q588,505 556.5,536.5Q525,568 480,568ZM480,760Q334,760 214,678.5Q94,597 40,460Q94,323 214,241.5Q334,160 480,160Q621,160 737.5,236Q854,312 912,440L760,440Q732,440 707,447Q682,454 660,467Q660,465 660,463.5Q660,462 660,460Q660,385 607.5,332.5Q555,280 480,280Q405,280 352.5,332.5Q300,385 300,460Q300,535 352.5,587.5Q405,640 480,640Q502,640 522.5,635Q543,630 561,621Q560,626 560,630.5Q560,635 560,640L560,753Q540,756 520,758Q500,760 480,760ZM680,840Q663,840 651.5,828.5Q640,817 640,800L640,680Q640,663 651.5,651.5Q663,640 680,640L680,640L680,600Q680,567 703.5,543.5Q727,520 760,520Q793,520 816.5,543.5Q840,567 840,600L840,640L840,640Q857,640 868.5,651.5Q880,663 880,680L880,800Q880,817 868.5,828.5Q857,840 840,840L680,840ZM720,640L800,640L800,600Q800,583 788.5,571.5Q777,560 760,560Q743,560 731.5,571.5Q720,583 720,600L720,640Z"/>
|
||||
</vector>
|
||||
29
res/drawable/ic_settings_safety_center_filled.xml
Normal file
29
res/drawable/ic_settings_safety_center_filled.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M4,2h16v20h-16z"/>
|
||||
<path
|
||||
android:pathData="M18.92,4.4L12.56,2.1C12.38,2.03 12.19,2 12,2C11.81,2 11.62,2.03 11.44,2.1L5.08,4.4C4.43,4.63 4,5.25 4,5.94V10.32C4.02,11.07 4.07,11.79 4.17,12.54C4.64,15.72 6.44,19.33 11.37,21.85C11.57,21.95 11.78,22 12,22C12.22,22 12.43,21.95 12.63,21.85C13.08,21.62 13.5,21.37 13.9,21.12C14.04,21.05 14.18,20.96 14.32,20.86C17.98,18.43 19.41,15.32 19.82,12.54C19.92,11.8 19.98,11.07 19.99,10.32V5.94C19.99,5.25 19.56,4.64 18.91,4.4H18.92ZM12.25,19.78C12.1,19.87 11.9,19.87 11.74,19.78C8.5,17.97 6.62,15.43 6.15,12.27C6.06,11.59 6.01,10.94 6,10.32V6.55C6,6.34 6.13,6.15 6.33,6.08L8.26,5.38C8.11,5.89 8.03,6.44 8.03,7.04C8.04,8.91 9.03,10.68 10.7,11.8C11.15,12.08 12.39,12.89 12.78,13.19C13.27,13.57 13.95,14.21 14.26,14.74C15.29,16.52 14.26,18.46 13.1,19.27C12.83,19.45 12.55,19.62 12.25,19.79V19.78ZM17.85,12.24C17.66,13.49 17.26,14.63 16.65,15.68C16.57,15.04 16.37,14.38 15.99,13.74C15.42,12.75 14.33,11.86 14.01,11.61C13.47,11.19 11.94,10.22 11.79,10.12C10.69,9.39 10.04,8.23 10.03,6.99C10.03,5.01 11.25,4.34 11.98,4.12C12.08,4.09 12.19,4.1 12.29,4.13L17.68,6.08C17.88,6.15 18.01,6.34 18.01,6.55V10.28C18,10.94 17.95,11.59 17.86,12.24H17.85Z"
|
||||
android:fillColor="@android:color/white"/>
|
||||
</group>
|
||||
</vector>
|
||||
25
res/drawable/ic_settings_security_filled.xml
Normal file
25
res/drawable/ic_settings_security_filled.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M240,880Q207,880 183.5,856.5Q160,833 160,800L160,400Q160,367 183.5,343.5Q207,320 240,320L280,320L280,240Q280,157 338.5,98.5Q397,40 480,40Q563,40 621.5,98.5Q680,157 680,240L680,320L720,320Q753,320 776.5,343.5Q800,367 800,400L800,800Q800,833 776.5,856.5Q753,880 720,880L240,880ZM480,680Q513,680 536.5,656.5Q560,633 560,600Q560,567 536.5,543.5Q513,520 480,520Q447,520 423.5,543.5Q400,567 400,600Q400,633 423.5,656.5Q447,680 480,680ZM360,320L600,320L600,240Q600,190 565,155Q530,120 480,120Q430,120 395,155Q360,190 360,240L360,320Z"/>
|
||||
</vector>
|
||||
25
res/drawable/ic_settings_system_dashboard_filled.xml
Normal file
25
res/drawable/ic_settings_system_dashboard_filled.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M370,880L354,752Q341,747 329.5,740Q318,733 307,725L188,775L78,585L181,507Q180,500 180,493.5Q180,487 180,480Q180,473 180,466.5Q180,460 181,453L78,375L188,185L307,235Q318,227 330,220Q342,213 354,208L370,80L590,80L606,208Q619,213 630.5,220Q642,227 653,235L772,185L882,375L779,453Q780,460 780,466.5Q780,473 780,480Q780,487 780,493.5Q780,500 778,507L881,585L771,775L653,725Q642,733 630,740Q618,747 606,752L590,880L370,880ZM482,620Q540,620 581,579Q622,538 622,480Q622,422 581,381Q540,340 482,340Q423,340 382.5,381Q342,422 342,480Q342,538 382.5,579Q423,620 482,620Z"/>
|
||||
</vector>
|
||||
25
res/drawable/ic_settings_wallpaper_filled.xml
Normal file
25
res/drawable/ic_settings_wallpaper_filled.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,880Q398,880 325,848.5Q252,817 197.5,762.5Q143,708 111.5,635Q80,562 80,480Q80,397 112.5,324Q145,251 200.5,197Q256,143 330,111.5Q404,80 488,80Q568,80 639,107.5Q710,135 763.5,183.5Q817,232 848.5,298.5Q880,365 880,442Q880,557 810,618.5Q740,680 640,680L566,680Q557,680 553.5,685Q550,690 550,696Q550,708 565,730.5Q580,753 580,782Q580,832 552.5,856Q525,880 480,880ZM260,520Q286,520 303,503Q320,486 320,460Q320,434 303,417Q286,400 260,400Q234,400 217,417Q200,434 200,460Q200,486 217,503Q234,520 260,520ZM380,360Q406,360 423,343Q440,326 440,300Q440,274 423,257Q406,240 380,240Q354,240 337,257Q320,274 320,300Q320,326 337,343Q354,360 380,360ZM580,360Q606,360 623,343Q640,326 640,300Q640,274 623,257Q606,240 580,240Q554,240 537,257Q520,274 520,300Q520,326 537,343Q554,360 580,360ZM700,520Q726,520 743,503Q760,486 760,460Q760,434 743,417Q726,400 700,400Q674,400 657,417Q640,434 640,460Q640,486 657,503Q674,520 700,520Z"/>
|
||||
</vector>
|
||||
25
res/drawable/ic_settings_wireless_filled.xml
Normal file
25
res/drawable/ic_settings_wireless_filled.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M480,840Q438,840 409,811Q380,782 380,740Q380,698 409,669Q438,640 480,640Q522,640 551,669Q580,698 580,740Q580,782 551,811Q522,840 480,840ZM254,614L170,528Q229,469 308.5,434.5Q388,400 480,400Q572,400 651.5,435Q731,470 790,530L706,614Q662,570 604,545Q546,520 480,520Q414,520 356,545Q298,570 254,614ZM84,444L0,360Q92,266 215,213Q338,160 480,160Q622,160 745,213Q868,266 960,360L876,444Q799,367 697.5,323.5Q596,280 480,280Q364,280 262.5,323.5Q161,367 84,444Z"/>
|
||||
</vector>
|
||||
25
res/drawable/ic_storage_filled.xml
Normal file
25
res/drawable/ic_storage_filled.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M120,800L120,640L840,640L840,800L120,800ZM200,760L280,760L280,680L200,680L200,760ZM120,320L120,160L840,160L840,320L120,320ZM200,280L280,280L280,200L200,200L200,280ZM120,560L120,400L840,400L840,560L120,560ZM200,520L280,520L280,440L200,440L200,520Z"/>
|
||||
</vector>
|
||||
26
res/drawable/ic_volume_up_filled.xml
Normal file
26
res/drawable/ic_volume_up_filled.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT 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="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?android:attr/colorControlNormal"
|
||||
android:autoMirrored="true">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M560,829L560,747Q650,721 705,647Q760,573 760,479Q760,385 705,311Q650,237 560,211L560,129Q684,157 762,254.5Q840,352 840,479Q840,606 762,703.5Q684,801 560,829ZM120,600L120,360L280,360L480,160L480,800L280,600L120,600ZM560,640L560,318Q607,340 633.5,384Q660,428 660,480Q660,531 633.5,574.5Q607,618 560,640Z"/>
|
||||
</vector>
|
||||
@@ -39,6 +39,7 @@
|
||||
android:id="@+id/fingerprint_rename_field"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textCapWords"/>
|
||||
android:inputType="textCapWords"
|
||||
android:minHeight = "48dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
90
res/layout/homepage_preference_v2.xml
Normal file
90
res/layout/homepage_preference_v2.xml
Normal file
@@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:minHeight="72dp"
|
||||
android:gravity="center_vertical"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clipToPadding="false"
|
||||
android:baselineAligned="false">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/icon_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="40dp"
|
||||
android:gravity="end|center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="24dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<androidx.preference.internal.PreferenceImageView
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
app:maxWidth="40dp"
|
||||
app:maxHeight="40dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/text_frame"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingStart="@dimen/homepage_preference_text_padding_start"
|
||||
android:paddingEnd="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:textAlignment="viewStart"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||
android:hyphenationFrequency="normalFast"
|
||||
android:lineBreakWordStyle="phrase"
|
||||
android:ellipsize="marquee"/>
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@android:id/title"
|
||||
android:layout_alignStart="@android:id/title"
|
||||
android:layout_gravity="start"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="?androidprv:attr/materialColorOnSurfaceVariant"
|
||||
android:maxLines="4"
|
||||
android:hyphenationFrequency="normalFast"
|
||||
android:lineBreakWordStyle="phrase"
|
||||
style="@style/PreferenceSummaryTextStyle"/>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
44
res/layout/search_bar_unified_version.xml
Normal file
44
res/layout/search_bar_unified_version.xml
Normal file
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/SearchBarStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1">
|
||||
<Toolbar
|
||||
android:id="@+id/search_action_bar_unified"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/search_bar_height"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="24dp"
|
||||
android:background="@drawable/search_bar_selected_background"
|
||||
android:touchscreenBlocksFocus="false"
|
||||
android:nextFocusForward="@+id/homepage_container"
|
||||
android:contentInsetStartWithNavigation="@dimen/search_bar_content_inset"
|
||||
android:navigationIcon="@drawable/ic_homepage_search">
|
||||
<TextView
|
||||
android:id="@+id/search_bar_title"
|
||||
style="@style/TextAppearance.SearchBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="8dp"
|
||||
android:layout_gravity="start"
|
||||
android:text="@string/search_settings"/>
|
||||
</Toolbar>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
29
res/layout/settings_homepage_app_bar_unified_layout.xml
Normal file
29
res/layout/settings_homepage_app_bar_unified_layout.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/app_bar_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:padding="6dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<include layout="@layout/search_bar_unified_version"/>
|
||||
|
||||
</LinearLayout>
|
||||
80
res/layout/settings_homepage_container_v2.xml
Normal file
80
res/layout/settings_homepage_container_v2.xml
Normal file
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/settings_homepage_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/main_content_scrollable_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="com.android.settings.widget.HomepageAppBarScrollingViewBehavior">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/homepage_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/unified_suggestion_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/contextual_cards_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/contextual_card_side_margin"
|
||||
android:layout_marginEnd="@dimen/contextual_card_side_margin"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/main_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"/>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/app_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:touchscreenBlocksFocus="false"
|
||||
android:keyboardNavigationCluster="false">
|
||||
<LinearLayout
|
||||
android:id="@+id/app_bar_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:minHeight="76dp"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed">
|
||||
|
||||
<include
|
||||
android:id="@+id/homepage_app_bar_unified_view"
|
||||
layout="@layout/settings_homepage_app_bar_unified_layout"/>
|
||||
</LinearLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
@@ -257,7 +257,7 @@
|
||||
<bool name="config_show_device_header_in_device_info">true</bool>
|
||||
|
||||
<!-- Whether or not TopLevelSettings should force rounded icon for injected tiles -->
|
||||
<bool name="config_force_rounded_icon_TopLevelSettings">true</bool>
|
||||
<bool name="config_force_rounded_icon_TopLevelSettings">false</bool>
|
||||
|
||||
<!-- Whether dismissal timestamp should be kept before deletion -->
|
||||
<bool name="config_keep_contextual_card_dismissal_timestamp">false</bool>
|
||||
|
||||
@@ -672,8 +672,10 @@
|
||||
<string name="location_settings_footer_learn_more_content_description">
|
||||
Learn more about Location settings
|
||||
</string>
|
||||
<!-- Tooltip for switchbar on Chrome devices. [CHAR LIMIT=90]-->
|
||||
<string name="location_settings_tooltip_text_for_chrome">To change location access, go to Settings > Security and Privacy > Privacy controls</string>
|
||||
<!-- Tooltip for switchbar on ChromeOS devices. [CHAR LIMIT=NONE]-->
|
||||
<string name="location_settings_tooltip_text_for_chrome">
|
||||
To change go to ChromeOS Settings > Privacy and security > Privacy controls > Location access
|
||||
</string>
|
||||
|
||||
<!-- Main Settings screen setting option title for the item to take you to the accounts screen [CHAR LIMIT=22] -->
|
||||
<string name="account_settings_title">Accounts</string>
|
||||
@@ -4688,8 +4690,6 @@
|
||||
<string name="accessibility_color_contrast_intro">Higher contrast makes text, buttons, and icons stand out more. Choose the contrast that looks best to you.</string>
|
||||
<!-- Notes in color contrast page footer for something should be aware. [CHAR LIMIT=NONE] -->
|
||||
<string name="color_contrast_note">Some apps may not support all color and text contrast settings</string>
|
||||
<!-- Summary for the accessibility color setting. [CHAR LIMIT=NONE] -->
|
||||
<string name="accessibility_color_contrast_summary">Adjust how colors and text look against your screen\'s background color</string>
|
||||
<!-- Preview screen title on the color contrast page. [CHAR LIMIT=20] -->
|
||||
<string name="color_contrast_preview">Preview</string>
|
||||
<!-- Preview screen email sender's name on the color contrast page. [CHAR LIMIT=15] -->
|
||||
@@ -12579,11 +12579,17 @@
|
||||
<!-- Title for Thread network preference [CHAR_LIMIT=60] -->
|
||||
<string name="thread_network_settings_title">Thread</string>
|
||||
|
||||
<!-- Summary for Thread network preference. [CHAR_LIMIT=NONE]-->
|
||||
<string name="thread_network_settings_summary">Connect to compatible devices using Thread for a seamless smart home experience</string>
|
||||
<!-- Title for Thread network settings main switch [CHAR_LIMIT=60] -->
|
||||
<string name="thread_network_settings_main_switch_title">Use Thread</string>
|
||||
|
||||
<!-- Summary for Thread network preference when airplane mode is enabled. [CHAR_LIMIT=NONE]-->
|
||||
<string name="thread_network_settings_summary_airplane_mode">Turn off airplane mode to use Thread</string>
|
||||
<!-- Title for Thread network settings footer [CHAR_LIMIT=NONE] -->
|
||||
<string name="thread_network_settings_footer_title">Thread helps connect your smart home devices, boosting efficiency, and performance.\n\nWhen enabled, this device is eligible to join a Thread network, allowing control of Matter supported devices through this phone.</string>
|
||||
|
||||
<!-- Text for Thread network settings learn more link [CHAR_LIMIT=NONE] -->
|
||||
<string name="thread_network_settings_learn_more">Learn more about Thread</string>
|
||||
|
||||
<!-- URL for Thread network settings learn more link [CHAR_LIMIT=NONE] -->
|
||||
<string name="thread_network_settings_learn_more_link" translatable="false">https://developers.home.google.com</string>
|
||||
|
||||
<!-- Label for the camera use toggle [CHAR LIMIT=40] -->
|
||||
<string name="camera_toggle_title">Camera access</string>
|
||||
|
||||
@@ -21,16 +21,6 @@
|
||||
android:persistent="false"
|
||||
android:title="@string/accessibility_color_and_motion_title">
|
||||
|
||||
<Preference
|
||||
android:fragment="com.android.settings.accessibility.ColorContrastFragment"
|
||||
android:key="color_contrast"
|
||||
android:icon="@drawable/ic_color_contrast"
|
||||
android:persistent="false"
|
||||
android:title="@string/accessibility_color_contrast_title"
|
||||
android:summary="@string/accessibility_color_contrast_summary"
|
||||
settings:controller="com.android.settings.accessibility.ContrastPreferenceController"
|
||||
settings:searchable="true"/>
|
||||
|
||||
<Preference
|
||||
android:fragment="com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment"
|
||||
android:icon="@drawable/ic_daltonizer"
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
android:key="color_contrast_selector"
|
||||
android:selectable="false"
|
||||
android:layout="@layout/accessibility_color_contrast_selector"
|
||||
settings:controller="com.android.settings.accessibility.ContrastSelectorPreferenceController" />
|
||||
settings:controller="com.android.settings.display.ContrastSelectorPreferenceController" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:key="toggle_high_text_contrast_preference"
|
||||
@@ -43,6 +43,6 @@
|
||||
android:title="@string/color_contrast_note"
|
||||
android:selectable="false"
|
||||
settings:searchable="false"
|
||||
settings:controller="com.android.settings.accessibility.ColorContrastFooterPreferenceController" />
|
||||
settings:controller="com.android.settings.display.ColorContrastFooterPreferenceController" />
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
@@ -46,6 +46,17 @@
|
||||
settings:controller="com.android.settings.wfd.WifiDisplayPreferenceController"
|
||||
settings:keywords="@string/keywords_wifi_display_settings" />
|
||||
|
||||
<com.android.settingslib.RestrictedPreference
|
||||
android:fragment="com.android.settings.connecteddevice.threadnetwork.ThreadNetworkFragment"
|
||||
android:key="thread_network_settings"
|
||||
android:title="@string/thread_network_settings_title"
|
||||
android:icon="@*android:drawable/ic_thread_network"
|
||||
android:order="-5"
|
||||
settings:searchable="false"
|
||||
settings:controller="com.android.settings.connecteddevice.threadnetwork.ThreadNetworkFragmentController"
|
||||
settings:userRestriction="no_thread_network"
|
||||
settings:useAdminDisabledSummary="true"/>
|
||||
|
||||
<com.android.settingslib.RestrictedPreference
|
||||
android:fragment="com.android.settings.print.PrintSettingsFragment"
|
||||
android:icon="@*android:drawable/ic_settings_print"
|
||||
@@ -63,15 +74,6 @@
|
||||
settings:useAdminDisabledSummary="true"
|
||||
settings:userRestriction="no_ultra_wideband_radio" />
|
||||
|
||||
<com.android.settingslib.RestrictedSwitchPreference
|
||||
android:key="thread_network_settings"
|
||||
android:title="@string/thread_network_settings_title"
|
||||
android:order="110"
|
||||
android:summary="@string/summary_placeholder"
|
||||
settings:controller="com.android.settings.connecteddevice.threadnetwork.ThreadNetworkPreferenceController"
|
||||
settings:userRestriction="no_thread_network"
|
||||
settings:useAdminDisabledSummary="true"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="dashboard_tile_placeholder"
|
||||
android:order="-8" />
|
||||
|
||||
@@ -111,6 +111,14 @@
|
||||
android:fragment="com.android.settings.display.ColorModePreferenceFragment"
|
||||
settings:controller="com.android.settings.display.ColorModePreferenceController"
|
||||
settings:keywords="@string/keywords_color_mode"/>
|
||||
|
||||
<Preference
|
||||
android:fragment="com.android.settings.display.ColorContrastFragment"
|
||||
android:key="color_contrast"
|
||||
android:persistent="false"
|
||||
android:title="@string/accessibility_color_contrast_title"
|
||||
settings:controller="com.android.settings.display.ContrastPreferenceController"
|
||||
settings:searchable="true"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
|
||||
33
res/xml/thread_network_settings.xml
Normal file
33
res/xml/thread_network_settings.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:title="@string/thread_network_settings_title">
|
||||
|
||||
<com.android.settingslib.widget.MainSwitchPreference
|
||||
android:key="toggle_thread_network"
|
||||
android:title="@string/thread_network_settings_main_switch_title"
|
||||
settings:controller="com.android.settings.connecteddevice.threadnetwork.ThreadNetworkToggleController"/>
|
||||
|
||||
<com.android.settingslib.widget.FooterPreference
|
||||
android:key="thread_network_settings_footer"
|
||||
android:title="@string/thread_network_settings_footer_title"
|
||||
android:selectable="false"
|
||||
settings:searchable="false"
|
||||
settings:controller="com.android.settings.connecteddevice.threadnetwork.ThreadNetworkFooterController"/>
|
||||
</PreferenceScreen>
|
||||
241
res/xml/top_level_settings_v2.xml
Normal file
241
res/xml/top_level_settings_v2.xml
Normal file
@@ -0,0 +1,241 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:key="top_level_settings">
|
||||
|
||||
<PreferenceCategory
|
||||
android:order="-140"
|
||||
android:key="top_level_account_category">
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:order="-130"
|
||||
android:key="top_level_connectivity_category">
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.network.NetworkDashboardFragment"
|
||||
android:icon="@drawable/ic_settings_wireless_filled"
|
||||
android:key="top_level_network"
|
||||
android:order="-20"
|
||||
android:title="@string/network_dashboard_title"
|
||||
android:summary="@string/summary_placeholder"
|
||||
settings:highlightableMenuKey="@string/menu_key_network"
|
||||
settings:controller="com.android.settings.network.TopLevelNetworkEntryPreferenceController"/>
|
||||
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment"
|
||||
android:icon="@drawable/ic_devices_other_filled"
|
||||
android:key="top_level_connected_devices"
|
||||
android:order="-10"
|
||||
android:title="@string/connected_devices_dashboard_title"
|
||||
android:summary="@string/connected_devices_dashboard_default_summary"
|
||||
settings:highlightableMenuKey="@string/menu_key_connected_devices"
|
||||
settings:controller="com.android.settings.connecteddevice.TopLevelConnectedDevicesPreferenceController"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:order="-120"
|
||||
android:key="top_level_personalize_category">
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.applications.AppDashboardFragment"
|
||||
android:icon="@drawable/ic_apps_filled"
|
||||
android:key="top_level_apps"
|
||||
android:order="-60"
|
||||
android:title="@string/apps_dashboard_title"
|
||||
android:summary="@string/app_and_notification_dashboard_summary"
|
||||
settings:highlightableMenuKey="@string/menu_key_apps"/>
|
||||
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.notification.ConfigureNotificationSettings"
|
||||
android:icon="@drawable/ic_notifications_filled"
|
||||
android:key="top_level_notifications"
|
||||
android:order="-50"
|
||||
android:title="@string/configure_notification_settings"
|
||||
android:summary="@string/notification_dashboard_summary"
|
||||
settings:highlightableMenuKey="@string/menu_key_notifications"/>
|
||||
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.notification.SoundSettings"
|
||||
android:icon="@drawable/ic_volume_up_filled"
|
||||
android:key="top_level_sound"
|
||||
android:order="-40"
|
||||
android:title="@string/sound_settings"
|
||||
android:summary="@string/sound_dashboard_summary"
|
||||
settings:highlightableMenuKey="@string/menu_key_sound"/>
|
||||
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.communal.CommunalDashboardFragment"
|
||||
android:icon="@drawable/ia_settings_communal"
|
||||
android:key="top_level_communal"
|
||||
android:order="-30"
|
||||
android:title="@string/communal_settings_title"
|
||||
android:summary="@string/communal_settings_summary"
|
||||
settings:highlightableMenuKey="@string/menu_key_communal"
|
||||
settings:controller="com.android.settings.communal.CommunalPreferenceController"/>
|
||||
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.DisplaySettings"
|
||||
android:icon="@drawable/ic_settings_display_filled"
|
||||
android:key="top_level_display"
|
||||
android:order="-20"
|
||||
android:title="@string/display_settings"
|
||||
android:summary="@string/display_dashboard_summary"
|
||||
settings:highlightableMenuKey="@string/menu_key_display"
|
||||
settings:controller="com.android.settings.display.TopLevelDisplayPreferenceController"/>
|
||||
|
||||
<com.android.settings.widget.RestrictedHomepagePreference
|
||||
android:icon="@drawable/ic_settings_wallpaper_filled"
|
||||
android:key="top_level_wallpaper"
|
||||
android:order="-10"
|
||||
android:title="@string/wallpaper_settings_title"
|
||||
android:summary="@string/wallpaper_dashboard_summary"
|
||||
settings:highlightableMenuKey="@string/menu_key_wallpaper"
|
||||
settings:controller="com.android.settings.display.TopLevelWallpaperPreferenceController"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:order="-110"
|
||||
android:key="top_level_system_info_category">
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.deviceinfo.StorageDashboardFragment"
|
||||
android:icon="@drawable/ic_storage_filled"
|
||||
android:key="top_level_storage"
|
||||
android:order="-50"
|
||||
android:title="@string/storage_settings"
|
||||
android:summary="@string/summary_placeholder"
|
||||
settings:highlightableMenuKey="@string/menu_key_storage"
|
||||
settings:controller="com.android.settings.deviceinfo.TopLevelStoragePreferenceController"/>
|
||||
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.fuelgauge.batteryusage.PowerUsageSummary"
|
||||
android:icon="@drawable/ic_settings_battery_filled"
|
||||
android:key="top_level_battery"
|
||||
android:order="-30"
|
||||
android:title="@string/power_usage_summary_title"
|
||||
android:summary="@string/summary_placeholder"
|
||||
settings:highlightableMenuKey="@string/menu_key_battery"
|
||||
settings:controller="com.android.settings.fuelgauge.TopLevelBatteryPreferenceController"/>
|
||||
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.system.SystemDashboardFragment"
|
||||
android:icon="@drawable/ic_settings_system_dashboard_filled"
|
||||
android:key="top_level_system"
|
||||
android:order="-20"
|
||||
android:title="@string/header_category_system"
|
||||
android:summary="@string/system_dashboard_summary"
|
||||
settings:highlightableMenuKey="@string/menu_key_system"/>
|
||||
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment"
|
||||
android:icon="@drawable/ic_settings_about_device_filled"
|
||||
android:key="top_level_about_device"
|
||||
android:order="-10"
|
||||
android:title="@string/about_settings"
|
||||
android:summary="@string/summary_placeholder"
|
||||
settings:highlightableMenuKey="@string/menu_key_about_device"
|
||||
settings:controller="com.android.settings.deviceinfo.aboutphone.TopLevelAboutDevicePreferenceController"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:order="-100"
|
||||
android:key="top_level_security_privacy_category">
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:icon="@drawable/ic_settings_safety_center_filled"
|
||||
android:key="top_level_safety_center"
|
||||
android:order="-50"
|
||||
android:title="@string/safety_center_title"
|
||||
android:summary="@string/safety_center_summary"
|
||||
settings:highlightableMenuKey="@string/menu_key_safety_center"
|
||||
settings:controller="com.android.settings.safetycenter.TopLevelSafetyCenterEntryPreferenceController"/>
|
||||
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.security.SecuritySettings"
|
||||
android:icon="@drawable/ic_settings_security_filled"
|
||||
android:key="top_level_security"
|
||||
android:order="-40"
|
||||
android:title="@string/security_settings_title"
|
||||
android:summary="@string/security_dashboard_summary"
|
||||
settings:highlightableMenuKey="@string/menu_key_security"
|
||||
settings:controller="com.android.settings.security.TopLevelSecurityEntryPreferenceController"/>
|
||||
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.privacy.PrivacyDashboardFragment"
|
||||
android:icon="@drawable/ic_settings_privacy_filled"
|
||||
android:key="top_level_privacy"
|
||||
android:order="-30"
|
||||
android:title="@string/privacy_dashboard_title"
|
||||
android:summary="@string/privacy_dashboard_summary"
|
||||
settings:highlightableMenuKey="@string/menu_key_privacy"
|
||||
settings:controller="com.android.settings.privacy.TopLevelPrivacyEntryPreferenceController"/>
|
||||
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.location.LocationSettings"
|
||||
android:icon="@drawable/ic_settings_location_filled"
|
||||
android:key="top_level_location"
|
||||
android:order="-20"
|
||||
android:title="@string/location_settings_title"
|
||||
android:summary="@string/location_settings_loading_app_permission_stats"
|
||||
settings:highlightableMenuKey="@string/menu_key_location"
|
||||
settings:controller="com.android.settings.location.TopLevelLocationPreferenceController"/>
|
||||
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.accounts.AccountDashboardFragment"
|
||||
android:icon="@drawable/ic_settings_passwords_filled"
|
||||
android:key="top_level_accounts"
|
||||
android:order="-10"
|
||||
android:title="@string/account_dashboard_title_with_passkeys"
|
||||
android:summary="@string/summary_placeholder"
|
||||
settings:highlightableMenuKey="@string/menu_key_accounts"
|
||||
settings:controller="com.android.settings.accounts.TopLevelAccountEntryPreferenceController"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
android:order="100"
|
||||
android:key="top_level_support_category">
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:key="top_level_emergency"
|
||||
android:title="@string/emergency_settings_preference_title"
|
||||
android:summary="@string/emergency_dashboard_summary"
|
||||
android:icon="@drawable/ic_settings_emergency_filled"
|
||||
android:order="-30"
|
||||
android:fragment="com.android.settings.emergency.EmergencyDashboardFragment"
|
||||
settings:isPreferenceVisible="@bool/config_show_emergency_settings"
|
||||
settings:highlightableMenuKey="@string/menu_key_emergency"/>
|
||||
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:fragment="com.android.settings.accessibility.AccessibilitySettings"
|
||||
android:icon="@drawable/ic_settings_accessibility_filled"
|
||||
android:key="top_level_accessibility"
|
||||
android:order="-20"
|
||||
android:title="@string/accessibility_settings"
|
||||
android:summary="@string/accessibility_settings_summary"
|
||||
settings:highlightableMenuKey="@string/menu_key_accessibility"
|
||||
settings:controller="com.android.settings.accessibility.TopLevelAccessibilityPreferenceController"/>
|
||||
|
||||
<com.android.settings.widget.HomepagePreference
|
||||
android:icon="@drawable/ic_help_filled"
|
||||
android:key="top_level_support"
|
||||
android:order="-10"
|
||||
android:title="@string/page_tab_title_support"
|
||||
android:summary="@string/support_summary"
|
||||
settings:highlightableMenuKey="@string/menu_key_support"
|
||||
settings:controller="com.android.settings.support.SupportPreferenceController"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
/**
|
||||
* Controller for {@link ColorContrastFragment}.
|
||||
*/
|
||||
public class ContrastPreferenceController extends BasePreferenceController {
|
||||
|
||||
public ContrastPreferenceController(@NonNull Context context, @NonNull String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
// Hide color contrast entry point inside Accessibility settings.
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT 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.connecteddevice.threadnetwork
|
||||
|
||||
import android.net.thread.ThreadNetworkController
|
||||
import android.net.thread.ThreadNetworkController.StateCallback
|
||||
import android.net.thread.ThreadNetworkException
|
||||
import android.os.OutcomeReceiver
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import java.util.concurrent.Executor
|
||||
|
||||
/**
|
||||
* A testable interface for [ThreadNetworkController] which is `final`.
|
||||
*
|
||||
* We are in a awkward situation that Android API guideline suggest `final` for API classes
|
||||
* while Robolectric test is being deprecated for platform testing (See
|
||||
* tests/robotests/new_tests_hook.sh). This force us to use "mockito-target-extended" but it's
|
||||
* conflicting with the default "mockito-target" which is somehow indirectly depended by the
|
||||
* `SettingsUnitTests` target.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
interface BaseThreadNetworkController {
|
||||
fun setEnabled(
|
||||
enabled: Boolean,
|
||||
executor: Executor,
|
||||
receiver: OutcomeReceiver<Void?, ThreadNetworkException>
|
||||
)
|
||||
|
||||
fun registerStateCallback(executor: Executor, callback: StateCallback)
|
||||
|
||||
fun unregisterStateCallback(callback: StateCallback)
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT 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.connecteddevice.threadnetwork
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.android.settings.R
|
||||
import com.android.settings.core.BasePreferenceController
|
||||
import com.android.settingslib.HelpUtils
|
||||
import com.android.settingslib.widget.FooterPreference
|
||||
|
||||
/**
|
||||
* The footer preference controller for Thread settings in
|
||||
* "Connected devices > Connection preferences > Thread".
|
||||
*/
|
||||
class ThreadNetworkFooterController(
|
||||
context: Context,
|
||||
preferenceKey: String
|
||||
) : BasePreferenceController(context, preferenceKey) {
|
||||
override fun getAvailabilityStatus(): Int {
|
||||
// The thread_network_settings screen won't be displayed and it doesn't matter if this
|
||||
// controller always return AVAILABLE
|
||||
return AVAILABLE
|
||||
}
|
||||
|
||||
override fun displayPreference(screen: PreferenceScreen) {
|
||||
val footer: FooterPreference? = screen.findPreference(KEY_PREFERENCE_FOOTER)
|
||||
if (footer != null) {
|
||||
footer.setLearnMoreAction { _ -> openLocaleLearnMoreLink() }
|
||||
footer.setLearnMoreText(mContext.getString(R.string.thread_network_settings_learn_more))
|
||||
}
|
||||
}
|
||||
|
||||
private fun openLocaleLearnMoreLink() {
|
||||
val intent = HelpUtils.getHelpIntent(
|
||||
mContext,
|
||||
mContext.getString(R.string.thread_network_settings_learn_more_link),
|
||||
mContext::class.java.name
|
||||
)
|
||||
if (intent != null) {
|
||||
mContext.startActivity(intent)
|
||||
} else {
|
||||
Log.w(TAG, "HelpIntent is null")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "ThreadNetworkSettings"
|
||||
private const val KEY_PREFERENCE_FOOTER = "thread_network_settings_footer"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT 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.connecteddevice.threadnetwork
|
||||
|
||||
import android.app.settings.SettingsEnums
|
||||
import com.android.settings.R
|
||||
import com.android.settings.dashboard.DashboardFragment
|
||||
import com.android.settings.search.BaseSearchIndexProvider
|
||||
import com.android.settingslib.search.SearchIndexable
|
||||
|
||||
/** The fragment for Thread settings in "Connected devices > Connection preferences > Thread". */
|
||||
@SearchIndexable(forTarget = SearchIndexable.ALL and SearchIndexable.ARC.inv())
|
||||
class ThreadNetworkFragment : DashboardFragment() {
|
||||
override fun getPreferenceScreenResId() = R.xml.thread_network_settings
|
||||
|
||||
override fun getLogTag() = "ThreadNetworkFragment"
|
||||
|
||||
override fun getMetricsCategory() = SettingsEnums.CONNECTED_DEVICE_PREFERENCES_THREAD
|
||||
|
||||
companion object {
|
||||
/** For Search. */
|
||||
@JvmField
|
||||
val SEARCH_INDEX_DATA_PROVIDER = BaseSearchIndexProvider(R.xml.thread_network_settings)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT 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.connecteddevice.threadnetwork
|
||||
|
||||
import android.content.Context
|
||||
import android.net.thread.ThreadNetworkController
|
||||
import android.net.thread.ThreadNetworkController.StateCallback
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.android.settings.R
|
||||
import com.android.settings.core.BasePreferenceController
|
||||
import com.android.settings.flags.Flags
|
||||
import java.util.concurrent.Executor
|
||||
|
||||
/**
|
||||
* The fragment controller for Thread settings in
|
||||
* "Connected devices > Connection preferences > Thread".
|
||||
*/
|
||||
class ThreadNetworkFragmentController @VisibleForTesting constructor(
|
||||
context: Context,
|
||||
preferenceKey: String,
|
||||
private val executor: Executor,
|
||||
private val threadController: BaseThreadNetworkController?
|
||||
) : BasePreferenceController(context, preferenceKey), LifecycleEventObserver {
|
||||
private val stateCallback: StateCallback
|
||||
private var threadEnabled = false
|
||||
private var preference: Preference? = null
|
||||
|
||||
constructor(context: Context, preferenceKey: String) : this(
|
||||
context,
|
||||
preferenceKey,
|
||||
ContextCompat.getMainExecutor(context),
|
||||
ThreadNetworkUtils.getThreadNetworkController(context)
|
||||
)
|
||||
|
||||
init {
|
||||
stateCallback = newStateCallback()
|
||||
}
|
||||
|
||||
override fun getAvailabilityStatus(): Int {
|
||||
return if (!Flags.threadSettingsEnabled()) {
|
||||
CONDITIONALLY_UNAVAILABLE
|
||||
} else if (threadController == null) {
|
||||
UNSUPPORTED_ON_DEVICE
|
||||
} else {
|
||||
AVAILABLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSummary(): CharSequence {
|
||||
return if (threadEnabled) {
|
||||
mContext.getText(R.string.switch_on_text)
|
||||
} else {
|
||||
mContext.getText(R.string.switch_off_text)
|
||||
}
|
||||
}
|
||||
|
||||
override fun displayPreference(screen: PreferenceScreen) {
|
||||
super.displayPreference(screen)
|
||||
preference = screen.findPreference(preferenceKey)
|
||||
}
|
||||
|
||||
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
|
||||
if (threadController == null) {
|
||||
return
|
||||
}
|
||||
|
||||
when (event) {
|
||||
Lifecycle.Event.ON_START ->
|
||||
threadController.registerStateCallback(executor, stateCallback)
|
||||
|
||||
Lifecycle.Event.ON_STOP ->
|
||||
threadController.unregisterStateCallback(stateCallback)
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun newStateCallback(): StateCallback {
|
||||
return object : StateCallback {
|
||||
override fun onThreadEnableStateChanged(enabledState: Int) {
|
||||
threadEnabled = enabledState == ThreadNetworkController.STATE_ENABLED
|
||||
preference?.let { preference -> refreshSummary(preference) }
|
||||
}
|
||||
|
||||
override fun onDeviceRoleChanged(role: Int) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,236 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT 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.connecteddevice.threadnetwork
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.thread.ThreadNetworkController
|
||||
import android.net.thread.ThreadNetworkController.StateCallback
|
||||
import android.net.thread.ThreadNetworkException
|
||||
import android.net.thread.ThreadNetworkManager
|
||||
import android.os.OutcomeReceiver
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.android.settings.R
|
||||
import com.android.settings.core.TogglePreferenceController
|
||||
import com.android.settings.flags.Flags
|
||||
import java.util.concurrent.Executor
|
||||
|
||||
/** Controller for the "Thread" toggle in "Connected devices > Connection preferences". */
|
||||
class ThreadNetworkPreferenceController @VisibleForTesting constructor(
|
||||
context: Context,
|
||||
key: String,
|
||||
private val executor: Executor,
|
||||
private val threadController: BaseThreadNetworkController?
|
||||
) : TogglePreferenceController(context, key), LifecycleEventObserver {
|
||||
private val stateCallback: StateCallback
|
||||
private val airplaneModeReceiver: BroadcastReceiver
|
||||
private var threadEnabled = false
|
||||
private var airplaneModeOn = false
|
||||
private var preference: Preference? = null
|
||||
|
||||
/**
|
||||
* A testable interface for [ThreadNetworkController] which is `final`.
|
||||
*
|
||||
* We are in a awkward situation that Android API guideline suggest `final` for API classes
|
||||
* while Robolectric test is being deprecated for platform testing (See
|
||||
* tests/robotests/new_tests_hook.sh). This force us to use "mockito-target-extended" but it's
|
||||
* conflicting with the default "mockito-target" which is somehow indirectly depended by the
|
||||
* `SettingsUnitTests` target.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
interface BaseThreadNetworkController {
|
||||
fun setEnabled(
|
||||
enabled: Boolean,
|
||||
executor: Executor,
|
||||
receiver: OutcomeReceiver<Void?, ThreadNetworkException>
|
||||
)
|
||||
|
||||
fun registerStateCallback(executor: Executor, callback: StateCallback)
|
||||
|
||||
fun unregisterStateCallback(callback: StateCallback)
|
||||
}
|
||||
|
||||
constructor(context: Context, key: String) : this(
|
||||
context,
|
||||
key,
|
||||
ContextCompat.getMainExecutor(context),
|
||||
getThreadNetworkController(context)
|
||||
)
|
||||
|
||||
init {
|
||||
stateCallback = newStateCallback()
|
||||
airplaneModeReceiver = newAirPlaneModeReceiver()
|
||||
}
|
||||
|
||||
val isThreadSupportedOnDevice: Boolean
|
||||
get() = threadController != null
|
||||
|
||||
private fun newStateCallback(): StateCallback {
|
||||
return object : StateCallback {
|
||||
override fun onThreadEnableStateChanged(enabledState: Int) {
|
||||
threadEnabled = enabledState == ThreadNetworkController.STATE_ENABLED
|
||||
}
|
||||
|
||||
override fun onDeviceRoleChanged(role: Int) {}
|
||||
}
|
||||
}
|
||||
|
||||
private fun newAirPlaneModeReceiver(): BroadcastReceiver {
|
||||
return object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
airplaneModeOn = isAirplaneModeOn(context)
|
||||
Log.i(TAG, "Airplane mode is " + if (airplaneModeOn) "ON" else "OFF")
|
||||
preference?.let { preference -> updateState(preference) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAvailabilityStatus(): Int {
|
||||
return if (!Flags.threadSettingsEnabled()) {
|
||||
CONDITIONALLY_UNAVAILABLE
|
||||
} else if (!isThreadSupportedOnDevice) {
|
||||
UNSUPPORTED_ON_DEVICE
|
||||
} else if (airplaneModeOn) {
|
||||
DISABLED_DEPENDENT_SETTING
|
||||
} else {
|
||||
AVAILABLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun displayPreference(screen: PreferenceScreen) {
|
||||
super.displayPreference(screen)
|
||||
preference = screen.findPreference(preferenceKey)
|
||||
}
|
||||
|
||||
override fun isChecked(): Boolean {
|
||||
// TODO (b/322742298):
|
||||
// Check airplane mode here because it's planned to disable Thread state in airplane mode
|
||||
// (code in the mainline module). But it's currently not implemented yet (b/322742298).
|
||||
// By design, the toggle should be unchecked in airplane mode, so explicitly check the
|
||||
// airplane mode here to acchieve the same UX.
|
||||
return !airplaneModeOn && threadEnabled
|
||||
}
|
||||
|
||||
override fun setChecked(isChecked: Boolean): Boolean {
|
||||
if (threadController == null) {
|
||||
return false
|
||||
}
|
||||
val action = if (isChecked) "enable" else "disable"
|
||||
threadController.setEnabled(
|
||||
isChecked,
|
||||
executor,
|
||||
object : OutcomeReceiver<Void?, ThreadNetworkException> {
|
||||
override fun onError(e: ThreadNetworkException) {
|
||||
// TODO(b/327549838): gracefully handle the failure by resetting the UI state
|
||||
Log.e(TAG, "Failed to $action Thread", e)
|
||||
}
|
||||
|
||||
override fun onResult(unused: Void?) {
|
||||
Log.d(TAG, "Successfully $action Thread")
|
||||
}
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
|
||||
if (threadController == null) {
|
||||
return
|
||||
}
|
||||
|
||||
when (event) {
|
||||
Lifecycle.Event.ON_START -> {
|
||||
threadController.registerStateCallback(executor, stateCallback)
|
||||
airplaneModeOn = isAirplaneModeOn(mContext)
|
||||
mContext.registerReceiver(
|
||||
airplaneModeReceiver,
|
||||
IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)
|
||||
)
|
||||
preference?.let { preference -> updateState(preference) }
|
||||
}
|
||||
Lifecycle.Event.ON_STOP -> {
|
||||
threadController.unregisterStateCallback(stateCallback)
|
||||
mContext.unregisterReceiver(airplaneModeReceiver)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateState(preference: Preference) {
|
||||
super.updateState(preference)
|
||||
preference.isEnabled = !airplaneModeOn
|
||||
refreshSummary(preference)
|
||||
}
|
||||
|
||||
override fun getSummary(): CharSequence {
|
||||
val resId: Int = if (airplaneModeOn) {
|
||||
R.string.thread_network_settings_summary_airplane_mode
|
||||
} else {
|
||||
R.string.thread_network_settings_summary
|
||||
}
|
||||
return mContext.getResources().getString(resId)
|
||||
}
|
||||
|
||||
override fun getSliceHighlightMenuRes(): Int {
|
||||
return R.string.menu_key_connected_devices
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "ThreadNetworkSettings"
|
||||
private fun getThreadNetworkController(context: Context): BaseThreadNetworkController? {
|
||||
if (!context.packageManager.hasSystemFeature(PackageManager.FEATURE_THREAD_NETWORK)) {
|
||||
return null
|
||||
}
|
||||
val manager = context.getSystemService(ThreadNetworkManager::class.java) ?: return null
|
||||
val controller = manager.allThreadNetworkControllers[0]
|
||||
return object : BaseThreadNetworkController {
|
||||
override fun setEnabled(
|
||||
enabled: Boolean,
|
||||
executor: Executor,
|
||||
receiver: OutcomeReceiver<Void?, ThreadNetworkException>
|
||||
) {
|
||||
controller.setEnabled(enabled, executor, receiver)
|
||||
}
|
||||
|
||||
override fun registerStateCallback(executor: Executor, callback: StateCallback) {
|
||||
controller.registerStateCallback(executor, callback)
|
||||
}
|
||||
|
||||
override fun unregisterStateCallback(callback: StateCallback) {
|
||||
controller.unregisterStateCallback(callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isAirplaneModeOn(context: Context): Boolean {
|
||||
return Settings.Global.getInt(
|
||||
context.contentResolver,
|
||||
Settings.Global.AIRPLANE_MODE_ON,
|
||||
0
|
||||
) == 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT 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.connecteddevice.threadnetwork
|
||||
|
||||
import android.content.Context
|
||||
import android.net.thread.ThreadNetworkController
|
||||
import android.net.thread.ThreadNetworkController.StateCallback
|
||||
import android.net.thread.ThreadNetworkException
|
||||
import android.os.OutcomeReceiver
|
||||
import android.util.Log
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleEventObserver
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.android.settings.R
|
||||
import com.android.settings.core.TogglePreferenceController
|
||||
import com.android.settings.flags.Flags
|
||||
import java.util.concurrent.Executor
|
||||
|
||||
/**
|
||||
* Controller for the "Use Thread" toggle in "Connected devices > Connection preferences > Thread".
|
||||
*/
|
||||
class ThreadNetworkToggleController @VisibleForTesting constructor(
|
||||
context: Context,
|
||||
key: String,
|
||||
private val executor: Executor,
|
||||
private val threadController: BaseThreadNetworkController?
|
||||
) : TogglePreferenceController(context, key), LifecycleEventObserver {
|
||||
private val stateCallback: StateCallback
|
||||
private var threadEnabled = false
|
||||
private var preference: Preference? = null
|
||||
|
||||
constructor(context: Context, key: String) : this(
|
||||
context,
|
||||
key,
|
||||
ContextCompat.getMainExecutor(context),
|
||||
ThreadNetworkUtils.getThreadNetworkController(context)
|
||||
)
|
||||
|
||||
init {
|
||||
stateCallback = newStateCallback()
|
||||
}
|
||||
|
||||
val isThreadSupportedOnDevice: Boolean
|
||||
get() = threadController != null
|
||||
|
||||
private fun newStateCallback(): StateCallback {
|
||||
return object : StateCallback {
|
||||
override fun onThreadEnableStateChanged(enabledState: Int) {
|
||||
threadEnabled = enabledState == ThreadNetworkController.STATE_ENABLED
|
||||
preference?.let { preference -> updateState(preference) }
|
||||
}
|
||||
|
||||
override fun onDeviceRoleChanged(role: Int) {}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getAvailabilityStatus(): Int {
|
||||
return if (!Flags.threadSettingsEnabled()) {
|
||||
CONDITIONALLY_UNAVAILABLE
|
||||
} else if (!isThreadSupportedOnDevice) {
|
||||
UNSUPPORTED_ON_DEVICE
|
||||
} else {
|
||||
AVAILABLE
|
||||
}
|
||||
}
|
||||
|
||||
override fun displayPreference(screen: PreferenceScreen) {
|
||||
super.displayPreference(screen)
|
||||
preference = screen.findPreference(preferenceKey)
|
||||
}
|
||||
|
||||
override fun isChecked(): Boolean {
|
||||
return threadEnabled
|
||||
}
|
||||
|
||||
override fun setChecked(isChecked: Boolean): Boolean {
|
||||
if (threadController == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Avoids dead loop of setChecked -> threadController.setEnabled() ->
|
||||
// StateCallback.onThreadEnableStateChanged -> updateState -> setChecked
|
||||
if (isChecked == isChecked()) {
|
||||
return true
|
||||
}
|
||||
|
||||
val action = if (isChecked) "enable" else "disable"
|
||||
threadController.setEnabled(
|
||||
isChecked,
|
||||
executor,
|
||||
object : OutcomeReceiver<Void?, ThreadNetworkException> {
|
||||
override fun onError(e: ThreadNetworkException) {
|
||||
// TODO(b/327549838): gracefully handle the failure by resetting the UI state
|
||||
Log.e(TAG, "Failed to $action Thread", e)
|
||||
}
|
||||
|
||||
override fun onResult(unused: Void?) {
|
||||
Log.d(TAG, "Successfully $action Thread")
|
||||
}
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
|
||||
if (threadController == null) {
|
||||
return
|
||||
}
|
||||
|
||||
when (event) {
|
||||
Lifecycle.Event.ON_START -> {
|
||||
threadController.registerStateCallback(executor, stateCallback)
|
||||
}
|
||||
|
||||
Lifecycle.Event.ON_STOP -> {
|
||||
threadController.unregisterStateCallback(stateCallback)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSliceHighlightMenuRes(): Int {
|
||||
return R.string.menu_key_connected_devices
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "ThreadNetworkSettings"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT 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.connecteddevice.threadnetwork
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.thread.ThreadNetworkController
|
||||
import android.net.thread.ThreadNetworkController.StateCallback
|
||||
import android.net.thread.ThreadNetworkException
|
||||
import android.net.thread.ThreadNetworkManager
|
||||
import android.os.OutcomeReceiver
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import java.util.concurrent.Executor
|
||||
|
||||
/** Common utilities for Thread settings classes. */
|
||||
object ThreadNetworkUtils {
|
||||
/**
|
||||
* Retrieves the [BaseThreadNetworkController] instance that is backed by the Android
|
||||
* [ThreadNetworkController].
|
||||
*/
|
||||
fun getThreadNetworkController(context: Context): BaseThreadNetworkController? {
|
||||
if (!context.packageManager.hasSystemFeature(PackageManager.FEATURE_THREAD_NETWORK)) {
|
||||
return null
|
||||
}
|
||||
val manager = context.getSystemService(ThreadNetworkManager::class.java) ?: return null
|
||||
val controller = manager.allThreadNetworkControllers[0]
|
||||
return object : BaseThreadNetworkController {
|
||||
override fun setEnabled(
|
||||
enabled: Boolean,
|
||||
executor: Executor,
|
||||
receiver: OutcomeReceiver<Void?, ThreadNetworkException>
|
||||
) {
|
||||
controller.setEnabled(enabled, executor, receiver)
|
||||
}
|
||||
|
||||
override fun registerStateCallback(executor: Executor, callback: StateCallback) {
|
||||
controller.registerStateCallback(executor, callback)
|
||||
}
|
||||
|
||||
override fun unregisterStateCallback(callback: StateCallback) {
|
||||
controller.unregisterStateCallback(callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
151
src/com/android/settings/core/RoundCornerPreferenceAdapter.java
Normal file
151
src/com/android/settings/core/RoundCornerPreferenceAdapter.java
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT 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.core;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
import androidx.preference.PreferenceGroupAdapter;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settingslib.widget.theme.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class RoundCornerPreferenceAdapter extends PreferenceGroupAdapter {
|
||||
|
||||
private static final int ROUND_CORNER_CENTER = 1;
|
||||
private static final int ROUND_CORNER_TOP = 1 << 1;
|
||||
private static final int ROUND_CORNER_BOTTOM = 1 << 2;
|
||||
|
||||
private final PreferenceGroup mPreferenceGroup;
|
||||
|
||||
private List<Integer> mRoundCornerMappingList;
|
||||
|
||||
private final Handler mHandler;
|
||||
|
||||
private final Runnable mSyncRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updatePreferences();
|
||||
}
|
||||
};
|
||||
|
||||
public RoundCornerPreferenceAdapter(@NonNull PreferenceGroup preferenceGroup) {
|
||||
super(preferenceGroup);
|
||||
mPreferenceGroup = preferenceGroup;
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
updatePreferences();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreferenceHierarchyChange(@NonNull Preference preference) {
|
||||
super.onPreferenceHierarchyChange(preference);
|
||||
mHandler.removeCallbacks(mSyncRunnable);
|
||||
mHandler.post(mSyncRunnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull PreferenceViewHolder holder, int position) {
|
||||
super.onBindViewHolder(holder, position);
|
||||
updateBackground(holder, position);
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess") /* synthetic access */
|
||||
private void updatePreferences() {
|
||||
mRoundCornerMappingList = new ArrayList<>();
|
||||
mappingPreferenceGroup(mRoundCornerMappingList, mPreferenceGroup);
|
||||
}
|
||||
private void mappingPreferenceGroup(List<Integer> visibleList, PreferenceGroup group) {
|
||||
int groupSize = group.getPreferenceCount();
|
||||
int firstVisible = 0;
|
||||
int lastVisible = 0;
|
||||
for (int i = 0; i < groupSize; i++) {
|
||||
Preference pref = group.getPreference(i);
|
||||
if (!pref.isVisible()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//the first visible preference.
|
||||
Preference firstVisiblePref = group.getPreference(firstVisible);
|
||||
if (!firstVisiblePref.isVisible()) {
|
||||
firstVisible = i;
|
||||
}
|
||||
|
||||
int value = 0;
|
||||
if (group instanceof PreferenceCategory) {
|
||||
if (pref instanceof PreferenceCategory) {
|
||||
visibleList.add(value);
|
||||
mappingPreferenceGroup(visibleList, (PreferenceCategory) pref);
|
||||
} else {
|
||||
if (i == firstVisible) {
|
||||
value |= ROUND_CORNER_TOP;
|
||||
}
|
||||
|
||||
value |= ROUND_CORNER_BOTTOM;
|
||||
if (i > lastVisible) {
|
||||
// the last
|
||||
int lastIndex = visibleList.size() - 1;
|
||||
int newValue = visibleList.get(lastIndex) & ~ROUND_CORNER_BOTTOM;
|
||||
visibleList.set(lastIndex, newValue);
|
||||
lastVisible = i;
|
||||
}
|
||||
|
||||
value |= ROUND_CORNER_CENTER;
|
||||
visibleList.add(value);
|
||||
}
|
||||
} else {
|
||||
visibleList.add(value);
|
||||
if (pref instanceof PreferenceCategory) {
|
||||
mappingPreferenceGroup(visibleList, (PreferenceCategory) pref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** handle roundCorner background */
|
||||
private void updateBackground(PreferenceViewHolder holder, int position) {
|
||||
int CornerType = mRoundCornerMappingList.get(position);
|
||||
|
||||
if ((CornerType & ROUND_CORNER_CENTER) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
View v = holder.itemView;
|
||||
if (((CornerType & ROUND_CORNER_TOP) != 0) && ((CornerType & ROUND_CORNER_BOTTOM) == 0)) {
|
||||
// the first
|
||||
v.setBackgroundResource(R.drawable.settingslib_round_background_top);
|
||||
} else if (((CornerType & ROUND_CORNER_BOTTOM) != 0)
|
||||
&& ((CornerType & ROUND_CORNER_TOP) == 0)) {
|
||||
// the last
|
||||
v.setBackgroundResource(R.drawable.settingslib_round_background_bottom);
|
||||
} else if (((CornerType & ROUND_CORNER_TOP) != 0)
|
||||
&& ((CornerType & ROUND_CORNER_BOTTOM) != 0)) {
|
||||
// the only one preference
|
||||
v.setBackgroundResource(R.drawable.settingslib_round_background);
|
||||
} else {
|
||||
// in the center
|
||||
v.setBackgroundResource(R.drawable.settingslib_round_background_center);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,6 @@ import com.android.settings.accessibility.AccessibilitySettings;
|
||||
import com.android.settings.accessibility.AccessibilitySettingsForSetupWizard;
|
||||
import com.android.settings.accessibility.CaptioningPropertiesFragment;
|
||||
import com.android.settings.accessibility.ColorAndMotionFragment;
|
||||
import com.android.settings.accessibility.ColorContrastFragment;
|
||||
import com.android.settings.accessibility.HearingDevicePairingFragment;
|
||||
import com.android.settings.accessibility.TextReadingPreferenceFragment;
|
||||
import com.android.settings.accessibility.TextReadingPreferenceFragmentForSetupWizard;
|
||||
@@ -105,6 +104,7 @@ import com.android.settings.deviceinfo.batteryinfo.BatteryInfoFragment;
|
||||
import com.android.settings.deviceinfo.firmwareversion.FirmwareVersionSettings;
|
||||
import com.android.settings.deviceinfo.legal.ModuleLicensesDashboard;
|
||||
import com.android.settings.display.AutoBrightnessSettings;
|
||||
import com.android.settings.display.ColorContrastFragment;
|
||||
import com.android.settings.display.NightDisplaySettings;
|
||||
import com.android.settings.display.ScreenTimeoutSettings;
|
||||
import com.android.settings.display.SmartAutoRotatePreferenceFragment;
|
||||
|
||||
@@ -444,7 +444,9 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
|
||||
}
|
||||
if (TextUtils.equals(tile.getCategory(), CategoryKey.CATEGORY_HOMEPAGE)) {
|
||||
iconDrawable.setTint(Utils.getHomepageIconColor(preference.getContext()));
|
||||
} else if (forceRoundedIcon && !TextUtils.equals(mContext.getPackageName(), iconPackage)) {
|
||||
}
|
||||
|
||||
if (forceRoundedIcon && !TextUtils.equals(mContext.getPackageName(), iconPackage)) {
|
||||
iconDrawable = new AdaptiveIcon(mContext, iconDrawable,
|
||||
R.dimen.dashboard_tile_foreground_image_inset);
|
||||
((AdaptiveIcon) iconDrawable).setBackgroundColor(mContext, tile);
|
||||
|
||||
@@ -26,11 +26,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.android.settings.R
|
||||
import com.android.settings.core.SubSettingLauncher
|
||||
import com.android.settings.datausage.lib.BillingCycleRepository
|
||||
import com.android.settings.network.mobileDataEnabledFlow
|
||||
import com.android.settings.spa.preference.ComposePreference
|
||||
import com.android.settingslib.spa.widget.preference.Preference
|
||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
/**
|
||||
* Preference which displays billing cycle of subscription
|
||||
@@ -46,8 +44,8 @@ class BillingCyclePreference @JvmOverloads constructor(
|
||||
|
||||
override fun setTemplate(template: NetworkTemplate, subId: Int) {
|
||||
setContent {
|
||||
val isModifiable by remember {
|
||||
context.mobileDataEnabledFlow(subId).map { repository.isModifiable(subId) }
|
||||
val isModifiable by remember(subId) {
|
||||
repository.isModifiableFlow(subId)
|
||||
}.collectAsStateWithLifecycle(initialValue = false)
|
||||
|
||||
Preference(object : PreferenceModel {
|
||||
|
||||
@@ -35,7 +35,7 @@ import com.android.settings.datausage.lib.BillingCycleRepository
|
||||
import com.android.settings.datausage.lib.NetworkUsageData
|
||||
import com.android.settings.network.MobileNetworkRepository
|
||||
import com.android.settings.network.SubscriptionUtil
|
||||
import com.android.settings.network.mobileDataEnabledFlow
|
||||
import com.android.settings.network.telephony.requireSubscriptionManager
|
||||
import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity
|
||||
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
||||
import com.android.settingslib.spaprivileged.framework.common.userManager
|
||||
@@ -113,8 +113,8 @@ open class DataUsageList : DashboardFragment() {
|
||||
override fun onViewCreated(v: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(v, savedInstanceState)
|
||||
|
||||
requireContext().mobileDataEnabledFlow(subId)
|
||||
.collectLatestWithLifecycle(viewLifecycleOwner) { updatePolicy() }
|
||||
billingCycleRepository.isModifiableFlow(subId)
|
||||
.collectLatestWithLifecycle(viewLifecycleOwner, action = ::updatePolicy)
|
||||
|
||||
val template = template ?: return
|
||||
viewModel.templateFlow.value = template
|
||||
@@ -163,16 +163,14 @@ open class DataUsageList : DashboardFragment() {
|
||||
}
|
||||
|
||||
/** Update chart sweeps and cycle list to reflect [NetworkPolicy] for current [template]. */
|
||||
private fun updatePolicy() {
|
||||
val isBillingCycleModifiable = isBillingCycleModifiable()
|
||||
private fun updatePolicy(isModifiable: Boolean) {
|
||||
val isBillingCycleModifiable = isModifiable && isActiveSubscription()
|
||||
dataUsageListHeaderController?.setConfigButtonVisible(isBillingCycleModifiable)
|
||||
chartDataUsagePreferenceController?.setBillingCycleModifiable(isBillingCycleModifiable)
|
||||
}
|
||||
|
||||
private fun isBillingCycleModifiable(): Boolean =
|
||||
billingCycleRepository.isModifiable(subId) &&
|
||||
requireContext().getSystemService(SubscriptionManager::class.java)!!
|
||||
.getActiveSubscriptionInfo(subId) != null
|
||||
private fun isActiveSubscription(): Boolean =
|
||||
requireContext().requireSubscriptionManager().getActiveSubscriptionInfo(subId) != null
|
||||
|
||||
/**
|
||||
* Updates the chart and detail data when initial loaded or selected cycle changed.
|
||||
|
||||
@@ -19,10 +19,15 @@ package com.android.settings.datausage.lib
|
||||
import android.content.Context
|
||||
import android.os.INetworkManagementService
|
||||
import android.os.ServiceManager
|
||||
import android.telephony.TelephonyManager
|
||||
import android.util.Log
|
||||
import androidx.annotation.OpenForTesting
|
||||
import com.android.settings.network.telephony.TelephonyRepository
|
||||
import com.android.settingslib.spaprivileged.framework.common.userManager
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
@OpenForTesting
|
||||
open class BillingCycleRepository @JvmOverloads constructor(
|
||||
@@ -31,12 +36,14 @@ open class BillingCycleRepository @JvmOverloads constructor(
|
||||
INetworkManagementService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)
|
||||
),
|
||||
private val telephonyRepository: TelephonyRepository = TelephonyRepository(context),
|
||||
) {
|
||||
private val userManager = context.userManager
|
||||
private val telephonyManager = context.getSystemService(TelephonyManager::class.java)!!
|
||||
|
||||
fun isModifiable(subId: Int): Boolean =
|
||||
isBandwidthControlEnabled() && userManager.isAdminUser && isDataEnabled(subId)
|
||||
fun isModifiableFlow(subId: Int): Flow<Boolean> =
|
||||
telephonyRepository.isDataEnabledFlow(subId).map { isDataEnabled ->
|
||||
isDataEnabled && isBandwidthControlEnabled() && userManager.isAdminUser
|
||||
}.conflate().flowOn(Dispatchers.Default)
|
||||
|
||||
open fun isBandwidthControlEnabled(): Boolean = try {
|
||||
networkService.isBandwidthControlEnabled
|
||||
@@ -45,10 +52,6 @@ open class BillingCycleRepository @JvmOverloads constructor(
|
||||
false
|
||||
}
|
||||
|
||||
private fun isDataEnabled(subId: Int): Boolean =
|
||||
telephonyManager.createForSubscriptionId(subId)
|
||||
.isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER)
|
||||
|
||||
companion object {
|
||||
private const val TAG = "BillingCycleRepository"
|
||||
}
|
||||
|
||||
@@ -69,12 +69,19 @@ public class GrammaticalGenderPreferenceController extends DeveloperOptionsPrefe
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
final var oldValue = SystemProperties.getInt(GRAMMATICAL_GENDER_PROPERTY,
|
||||
Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED);
|
||||
SystemProperties.set(GRAMMATICAL_GENDER_PROPERTY, newValue.toString());
|
||||
updateState(mPreference);
|
||||
try {
|
||||
Configuration config = mActivityManager.getConfiguration();
|
||||
// Only apply the developer settings value if it is the one currently used,
|
||||
// otherwise it means there's some kind of override that we don't want to
|
||||
// touch here.
|
||||
if (config.getGrammaticalGender() == oldValue) {
|
||||
config.setGrammaticalGender(Integer.parseInt(newValue.toString()));
|
||||
mActivityManager.updatePersistentConfiguration(config);
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
// intentional no-op
|
||||
}
|
||||
|
||||
@@ -14,13 +14,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
package com.android.settings.display;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityFooterPreferenceController;
|
||||
|
||||
/** Preference controller for footer in color contrast page. */
|
||||
public class ColorContrastFooterPreferenceController extends
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
package com.android.settings.display;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
|
||||
@@ -29,7 +29,6 @@ public class ColorContrastFragment extends DashboardFragment {
|
||||
|
||||
private static final String TAG = "ColorContrastFragment";
|
||||
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.accessibility_color_contrast;
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.display;
|
||||
|
||||
import static android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_HIGH;
|
||||
import static android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_MEDIUM;
|
||||
import static android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_STANDARD;
|
||||
import static android.app.UiModeManager.ContrastUtils.toContrastLevel;
|
||||
|
||||
import android.app.UiModeManager;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.Flags;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Controller for {@link ColorContrastFragment}.
|
||||
*/
|
||||
public class ContrastPreferenceController extends BasePreferenceController {
|
||||
|
||||
public ContrastPreferenceController(@NonNull Context context, @NonNull String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return Flags.enableColorContrastControl() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
Map<Integer, Integer> mContrastLevelToResId = Map.ofEntries(
|
||||
Map.entry(CONTRAST_LEVEL_STANDARD, R.string.contrast_default),
|
||||
Map.entry(CONTRAST_LEVEL_MEDIUM, R.string.contrast_medium),
|
||||
Map.entry(CONTRAST_LEVEL_HIGH, R.string.contrast_high)
|
||||
);
|
||||
|
||||
float contrastLevel = mContext.getSystemService(UiModeManager.class).getContrast();
|
||||
return mContext.getString(mContrastLevelToResId.get(toContrastLevel(contrastLevel)));
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
package com.android.settings.display;
|
||||
|
||||
import static android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_HIGH;
|
||||
import static android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_MEDIUM;
|
||||
@@ -649,9 +649,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
||||
|
||||
private final class HourlyChartLabelTextGenerator extends BaseLabelTextGenerator
|
||||
implements BatteryChartViewModel.LabelTextGenerator {
|
||||
private static final int FULL_CHARGE_BATTERY_LEVEL = 100;
|
||||
|
||||
private boolean mIsFromFullCharge;
|
||||
private boolean mIsStartTimestamp;
|
||||
private long mFistTimestamp;
|
||||
private long mLatestTimestamp;
|
||||
|
||||
@@ -664,7 +662,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
||||
long timestamp = timestamps.get(index);
|
||||
boolean showMinute = false;
|
||||
if (Objects.equal(timestamp, mFistTimestamp)) {
|
||||
if (mIsFromFullCharge) {
|
||||
if (mIsStartTimestamp) {
|
||||
showMinute = true;
|
||||
} else {
|
||||
// starts from 7 days ago
|
||||
@@ -699,8 +697,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
|
||||
@NonNull final BatteryLevelData batteryLevelData) {
|
||||
BatteryLevelData.PeriodBatteryLevelData firstDayLevelData =
|
||||
batteryLevelData.getHourlyBatteryLevelsPerDay().get(0);
|
||||
this.mIsFromFullCharge =
|
||||
firstDayLevelData.getLevels().get(0) == FULL_CHARGE_BATTERY_LEVEL;
|
||||
this.mIsStartTimestamp = firstDayLevelData.isStartTimestamp();
|
||||
this.mFistTimestamp = firstDayLevelData.getTimestamps().get(0);
|
||||
this.mLatestTimestamp =
|
||||
getLast(
|
||||
|
||||
@@ -28,6 +28,7 @@ import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.util.Preconditions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -39,17 +40,24 @@ public final class BatteryLevelData {
|
||||
private static final long MIN_SIZE = 2;
|
||||
private static final long TIME_SLOT = DateUtils.HOUR_IN_MILLIS * 2;
|
||||
|
||||
// For testing only.
|
||||
@VisibleForTesting @Nullable static Calendar sTestCalendar;
|
||||
|
||||
/** A container for the battery timestamp and level data. */
|
||||
public static final class PeriodBatteryLevelData {
|
||||
// The length of mTimestamps and mLevels must be the same. mLevels[index] might be null when
|
||||
// there is no level data for the corresponding timestamp.
|
||||
private final List<Long> mTimestamps;
|
||||
private final List<Integer> mLevels;
|
||||
private final boolean mIsStartTimestamp;
|
||||
|
||||
public PeriodBatteryLevelData(
|
||||
@NonNull Map<Long, Integer> batteryLevelMap, @NonNull List<Long> timestamps) {
|
||||
@NonNull Map<Long, Integer> batteryLevelMap,
|
||||
@NonNull List<Long> timestamps,
|
||||
boolean isStartTimestamp) {
|
||||
mTimestamps = timestamps;
|
||||
mLevels = new ArrayList<>(timestamps.size());
|
||||
mIsStartTimestamp = isStartTimestamp;
|
||||
for (Long timestamp : timestamps) {
|
||||
mLevels.add(
|
||||
batteryLevelMap.containsKey(timestamp)
|
||||
@@ -66,6 +74,10 @@ public final class BatteryLevelData {
|
||||
return mLevels;
|
||||
}
|
||||
|
||||
public boolean isStartTimestamp() {
|
||||
return mIsStartTimestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
@@ -105,14 +117,21 @@ public final class BatteryLevelData {
|
||||
|
||||
final List<Long> timestampList = new ArrayList<>(batteryLevelMap.keySet());
|
||||
Collections.sort(timestampList);
|
||||
final long minTimestamp = timestampList.get(0);
|
||||
final long sixDaysAgoTimestamp =
|
||||
DatabaseUtils.getTimestampSixDaysAgo(sTestCalendar != null ? sTestCalendar : null);
|
||||
final boolean isStartTimestamp = minTimestamp > sixDaysAgoTimestamp;
|
||||
final List<Long> dailyTimestamps = getDailyTimestamps(timestampList);
|
||||
final List<List<Long>> hourlyTimestamps = getHourlyTimestamps(dailyTimestamps);
|
||||
|
||||
mDailyBatteryLevels = new PeriodBatteryLevelData(batteryLevelMap, dailyTimestamps);
|
||||
mDailyBatteryLevels =
|
||||
new PeriodBatteryLevelData(batteryLevelMap, dailyTimestamps, isStartTimestamp);
|
||||
mHourlyBatteryLevelsPerDay = new ArrayList<>(hourlyTimestamps.size());
|
||||
for (List<Long> hourlyTimestampsPerDay : hourlyTimestamps) {
|
||||
for (int i = 0; i < hourlyTimestamps.size(); i++) {
|
||||
final List<Long> hourlyTimestampsPerDay = hourlyTimestamps.get(i);
|
||||
mHourlyBatteryLevelsPerDay.add(
|
||||
new PeriodBatteryLevelData(batteryLevelMap, hourlyTimestampsPerDay));
|
||||
new PeriodBatteryLevelData(
|
||||
batteryLevelMap, hourlyTimestampsPerDay, isStartTimestamp && i == 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,9 +67,13 @@ public final class BootBroadcastReceiver extends BroadcastReceiver {
|
||||
refreshJobs(context);
|
||||
break;
|
||||
case Intent.ACTION_TIME_CHANGED:
|
||||
Log.d(TAG, "refresh job and clear all data from action=" + action);
|
||||
Log.d(TAG, "refresh job and clear data from action=" + action);
|
||||
DatabaseUtils.clearDataAfterTimeChangedIfNeeded(context, intent);
|
||||
break;
|
||||
case Intent.ACTION_TIMEZONE_CHANGED:
|
||||
Log.d(TAG, "refresh job and clear all data from action=" + action);
|
||||
DatabaseUtils.clearDataAfterTimeZoneChangedIfNeeded(context);
|
||||
break;
|
||||
default:
|
||||
Log.w(TAG, "receive unsupported action=" + action);
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.settings.fuelgauge.batteryusage;
|
||||
|
||||
import static android.content.Intent.FLAG_RECEIVER_REPLACE_PENDING;
|
||||
|
||||
import static com.android.settings.fuelgauge.batteryusage.ConvertUtils.utcToLocalTimeForLogging;
|
||||
|
||||
import android.app.usage.IUsageStatsManager;
|
||||
@@ -59,6 +57,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -436,6 +435,23 @@ public final class DatabaseUtils {
|
||||
});
|
||||
}
|
||||
|
||||
/** Clears data after a specific startTimestamp in the battery usage database. */
|
||||
public static void clearAllAfter(Context context, long startTimestamp) {
|
||||
AsyncTask.execute(
|
||||
() -> {
|
||||
try {
|
||||
final BatteryStateDatabase database =
|
||||
BatteryStateDatabase.getInstance(context.getApplicationContext());
|
||||
database.appUsageEventDao().clearAllAfter(startTimestamp);
|
||||
database.batteryEventDao().clearAllAfter(startTimestamp);
|
||||
database.batteryStateDao().clearAllAfter(startTimestamp);
|
||||
database.batteryUsageSlotDao().clearAllAfter(startTimestamp);
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG, "clearAllAfter() failed", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Clears all out-of-date data in the battery usage database. */
|
||||
public static void clearExpiredDataIfNeeded(Context context) {
|
||||
AsyncTask.execute(
|
||||
@@ -456,14 +472,14 @@ public final class DatabaseUtils {
|
||||
});
|
||||
}
|
||||
|
||||
/** Clears all data and jobs if current timestamp is out of the range of last recorded job. */
|
||||
/** Clears data after new updated time and refresh periodic job. */
|
||||
public static void clearDataAfterTimeChangedIfNeeded(Context context, Intent intent) {
|
||||
if ((intent.getFlags() & FLAG_RECEIVER_REPLACE_PENDING) != 0) {
|
||||
if ((intent.hasExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT))) {
|
||||
BatteryUsageLogUtils.writeLog(
|
||||
context,
|
||||
Action.TIME_UPDATED,
|
||||
"Database is not cleared because the time change intent is only"
|
||||
+ " for the existing pending receiver.");
|
||||
"Database is not cleared because the time change intent is"
|
||||
+ " for time format change");
|
||||
return;
|
||||
}
|
||||
AsyncTask.execute(
|
||||
@@ -480,6 +496,22 @@ public final class DatabaseUtils {
|
||||
});
|
||||
}
|
||||
|
||||
/** Clears all data and reset jobs if timezone changed. */
|
||||
public static void clearDataAfterTimeZoneChangedIfNeeded(Context context) {
|
||||
AsyncTask.execute(
|
||||
() -> {
|
||||
try {
|
||||
clearDataAfterTimeZoneChangedIfNeededInternal(context);
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG, "clearDataAfterTimeZoneChangedIfNeeded() failed", e);
|
||||
BatteryUsageLogUtils.writeLog(
|
||||
context,
|
||||
Action.TIMEZONE_UPDATED,
|
||||
"clearDataAfterTimeZoneChangedIfNeeded() failed" + e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Returns the timestamp for 00:00 6 days before the calendar date. */
|
||||
public static long getTimestampSixDaysAgo(Calendar calendar) {
|
||||
Calendar startCalendar =
|
||||
@@ -861,37 +893,38 @@ public final class DatabaseUtils {
|
||||
}
|
||||
|
||||
private static void clearDataAfterTimeChangedIfNeededInternal(Context context) {
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
final String logInfo =
|
||||
String.format(Locale.ENGLISH, "clear data after current time = %d", currentTime);
|
||||
Log.d(TAG, logInfo);
|
||||
BatteryUsageLogUtils.writeLog(context, Action.TIME_UPDATED, logInfo);
|
||||
DatabaseUtils.clearAllAfter(context, currentTime);
|
||||
PeriodicJobManager.getInstance(context).refreshJob(/* fromBoot= */ false);
|
||||
|
||||
final List<BatteryEvent> batteryLevelRecordEvents =
|
||||
DatabaseUtils.getBatteryEvents(
|
||||
context,
|
||||
Calendar.getInstance(),
|
||||
getLastFullChargeTime(context),
|
||||
BATTERY_LEVEL_RECORD_EVENTS);
|
||||
final long lastRecordTimestamp =
|
||||
batteryLevelRecordEvents.isEmpty()
|
||||
? INVALID_TIMESTAMP
|
||||
: batteryLevelRecordEvents.get(0).getTimestamp();
|
||||
final long nextRecordTimestamp =
|
||||
TimestampUtils.getNextEvenHourTimestamp(lastRecordTimestamp);
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
final boolean isOutOfTimeRange =
|
||||
lastRecordTimestamp == INVALID_TIMESTAMP
|
||||
|| currentTime < lastRecordTimestamp
|
||||
|| currentTime > nextRecordTimestamp;
|
||||
if (batteryLevelRecordEvents.isEmpty()) {
|
||||
// Take a snapshot of battery usage data immediately if there's no battery events.
|
||||
BatteryUsageDataLoader.enqueueWork(context, /* isFullChargeStart= */ true);
|
||||
}
|
||||
}
|
||||
|
||||
private static void clearDataAfterTimeZoneChangedIfNeededInternal(Context context) {
|
||||
final String logInfo =
|
||||
String.format(
|
||||
Locale.ENGLISH,
|
||||
"clear database = %b, current time = %d, last record time = %d",
|
||||
isOutOfTimeRange,
|
||||
currentTime,
|
||||
lastRecordTimestamp);
|
||||
"clear database for new time zone = %s",
|
||||
TimeZone.getDefault().toString());
|
||||
BatteryUsageLogUtils.writeLog(context, Action.TIMEZONE_UPDATED, logInfo);
|
||||
Log.d(TAG, logInfo);
|
||||
BatteryUsageLogUtils.writeLog(context, Action.TIME_UPDATED, logInfo);
|
||||
if (isOutOfTimeRange) {
|
||||
DatabaseUtils.clearAll(context);
|
||||
PeriodicJobManager.getInstance(context)
|
||||
.refreshJob(/* fromBoot= */ false);
|
||||
}
|
||||
PeriodicJobManager.getInstance(context).refreshJob(/* fromBoot= */ false);
|
||||
// Take a snapshot of battery usage data immediately
|
||||
BatteryUsageDataLoader.enqueueWork(context, /* isFullChargeStart= */ true);
|
||||
}
|
||||
|
||||
private static long loadLongFromContentProvider(
|
||||
|
||||
@@ -55,6 +55,10 @@ public interface AppUsageEventDao {
|
||||
@Query("DELETE FROM AppUsageEventEntity WHERE timestamp <= :timestamp")
|
||||
void clearAllBefore(long timestamp);
|
||||
|
||||
/** Deletes all recorded data after a specific timestamp. */
|
||||
@Query("DELETE FROM AppUsageEventEntity WHERE timestamp >= :timestamp")
|
||||
void clearAllAfter(long timestamp);
|
||||
|
||||
/** Clears all recorded data in the database. */
|
||||
@Query("DELETE FROM AppUsageEventEntity")
|
||||
void clearAll();
|
||||
|
||||
@@ -65,6 +65,10 @@ public interface BatteryEventDao {
|
||||
@Query("DELETE FROM BatteryEventEntity WHERE timestamp <= :timestamp")
|
||||
void clearAllBefore(long timestamp);
|
||||
|
||||
/** Deletes all recorded data after a specific timestamp. */
|
||||
@Query("DELETE FROM BatteryEventEntity WHERE timestamp >= :timestamp")
|
||||
void clearAllAfter(long timestamp);
|
||||
|
||||
/** Clears all recorded data in the database. */
|
||||
@Query("DELETE FROM BatteryEventEntity")
|
||||
void clearAll();
|
||||
|
||||
@@ -61,6 +61,10 @@ public interface BatteryStateDao {
|
||||
@Query("DELETE FROM BatteryState WHERE timestamp <= :timestamp")
|
||||
void clearAllBefore(long timestamp);
|
||||
|
||||
/** Deletes all recorded data after a specific timestamp. */
|
||||
@Query("DELETE FROM BatteryState WHERE timestamp >= :timestamp")
|
||||
void clearAllAfter(long timestamp);
|
||||
|
||||
/** Clears all recorded data in the database. */
|
||||
@Query("DELETE FROM BatteryState")
|
||||
void clearAll();
|
||||
|
||||
@@ -52,6 +52,10 @@ public interface BatteryUsageSlotDao {
|
||||
@Query("DELETE FROM BatteryUsageSlotEntity WHERE timestamp <= :timestamp")
|
||||
void clearAllBefore(long timestamp);
|
||||
|
||||
/** Deletes all recorded data after a specific timestamp. */
|
||||
@Query("DELETE FROM BatteryUsageSlotEntity WHERE timestamp >= :timestamp")
|
||||
void clearAllAfter(long timestamp);
|
||||
|
||||
/** Clears all recorded data in the database. */
|
||||
@Query("DELETE FROM BatteryUsageSlotEntity")
|
||||
void clearAll();
|
||||
|
||||
@@ -73,6 +73,7 @@ import com.android.settings.activityembedding.ActivityEmbeddingUtils;
|
||||
import com.android.settings.activityembedding.EmbeddedDeepLinkUtils;
|
||||
import com.android.settings.core.CategoryMixin;
|
||||
import com.android.settings.core.FeatureFlags;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.homepage.contextualcards.ContextualCardsFragment;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.safetycenter.SafetyCenterManagerWrapper;
|
||||
@@ -160,9 +161,13 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
if (mAllowUpdateSuggestion) {
|
||||
Log.i(TAG, "showHomepageWithSuggestion: " + showSuggestion);
|
||||
mAllowUpdateSuggestion = false;
|
||||
if (Flags.homepageRevamp()) {
|
||||
mSuggestionView.setVisibility(showSuggestion ? View.VISIBLE : View.GONE);
|
||||
} else {
|
||||
mSuggestionView.setVisibility(showSuggestion ? View.VISIBLE : View.GONE);
|
||||
mTwoPaneSuggestionView.setVisibility(showSuggestion ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
if (mHomepageView == null) {
|
||||
return;
|
||||
@@ -245,7 +250,10 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
}
|
||||
|
||||
setupEdgeToEdge();
|
||||
setContentView(R.layout.settings_homepage_container);
|
||||
setContentView(
|
||||
Flags.homepageRevamp()
|
||||
? R.layout.settings_homepage_container_v2
|
||||
: R.layout.settings_homepage_container);
|
||||
|
||||
mIsTwoPane = ActivityEmbeddingUtils.isAlreadyEmbedded(this);
|
||||
|
||||
@@ -397,9 +405,16 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
}
|
||||
|
||||
private void initSearchBarView() {
|
||||
if (Flags.homepageRevamp()) {
|
||||
Toolbar toolbar = findViewById(R.id.search_action_bar_unified);
|
||||
FeatureFactory.getFeatureFactory().getSearchFeatureProvider()
|
||||
.initSearchToolbar(this /* activity */, toolbar,
|
||||
SettingsEnums.SETTINGS_HOMEPAGE);
|
||||
} else {
|
||||
final Toolbar toolbar = findViewById(R.id.search_action_bar);
|
||||
FeatureFactory.getFeatureFactory().getSearchFeatureProvider()
|
||||
.initSearchToolbar(this /* activity */, toolbar, SettingsEnums.SETTINGS_HOMEPAGE);
|
||||
.initSearchToolbar(this /* activity */, toolbar,
|
||||
SettingsEnums.SETTINGS_HOMEPAGE);
|
||||
|
||||
if (mIsEmbeddingActivityEnabled) {
|
||||
final Toolbar toolbarTwoPaneVersion = findViewById(R.id.search_action_bar_two_pane);
|
||||
@@ -408,8 +423,13 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
SettingsEnums.SETTINGS_HOMEPAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initAvatarView() {
|
||||
if (Flags.homepageRevamp()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ImageView avatarView = findViewById(R.id.account_avatar);
|
||||
final ImageView avatarTwoPaneView = findViewById(R.id.account_avatar_two_pane_version);
|
||||
if (AvatarViewMixin.isAvatarSupported(this)) {
|
||||
@@ -458,8 +478,12 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
return;
|
||||
}
|
||||
|
||||
if (Flags.homepageRevamp()) {
|
||||
mSuggestionView = findViewById(R.id.unified_suggestion_content);
|
||||
} else {
|
||||
mSuggestionView = findViewById(R.id.suggestion_content);
|
||||
mTwoPaneSuggestionView = findViewById(R.id.two_pane_suggestion_content);
|
||||
}
|
||||
mHomepageView = findViewById(R.id.settings_homepage_container);
|
||||
// Hide the homepage for preparing the suggestion. If scrolling is needed, the list views
|
||||
// should be initialized in the invisible homepage view to prevent a scroll flicker.
|
||||
@@ -467,6 +491,10 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
// Schedule a timer to show the homepage and hide the suggestion on timeout.
|
||||
mHomepageView.postDelayed(() -> showHomepageWithSuggestion(false),
|
||||
HOMEPAGE_LOADING_TIMEOUT_MS);
|
||||
if (Flags.homepageRevamp()) {
|
||||
showFragment(new SuggestionFragCreator(fragmentClass, true),
|
||||
R.id.unified_suggestion_content);
|
||||
} else {
|
||||
showFragment(new SuggestionFragCreator(fragmentClass, /* isTwoPaneLayout= */ false),
|
||||
R.id.suggestion_content);
|
||||
if (mIsEmbeddingActivityEnabled) {
|
||||
@@ -474,6 +502,7 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
R.id.two_pane_suggestion_content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends Fragment> T showFragment(FragmentCreator<T> fragmentCreator, int id) {
|
||||
final FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
@@ -736,7 +765,7 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
}
|
||||
|
||||
private void updateHomepageAppBar() {
|
||||
if (!mIsEmbeddingActivityEnabled) {
|
||||
if (Flags.homepageRevamp() || !mIsEmbeddingActivityEnabled) {
|
||||
return;
|
||||
}
|
||||
updateAppBarMinHeight();
|
||||
@@ -752,7 +781,7 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
}
|
||||
|
||||
private void updateHomepagePaddings() {
|
||||
if (!mIsEmbeddingActivityEnabled) {
|
||||
if (Flags.homepageRevamp() || !mIsEmbeddingActivityEnabled) {
|
||||
return;
|
||||
}
|
||||
if (mIsTwoPane) {
|
||||
@@ -766,6 +795,9 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
||||
}
|
||||
|
||||
private void updateAppBarMinHeight() {
|
||||
if (Flags.homepageRevamp()) {
|
||||
return;
|
||||
}
|
||||
final int searchBarHeight = getResources().getDimensionPixelSize(R.dimen.search_bar_height);
|
||||
final int margin = getResources().getDimensionPixelSize(
|
||||
mIsEmbeddingActivityEnabled && mIsTwoPane
|
||||
|
||||
@@ -42,8 +42,10 @@ import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.activityembedding.ActivityEmbeddingRulesController;
|
||||
import com.android.settings.activityembedding.ActivityEmbeddingUtils;
|
||||
import com.android.settings.core.RoundCornerPreferenceAdapter;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.support.SupportPreferenceController;
|
||||
@@ -84,7 +86,7 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.top_level_settings;
|
||||
return Flags.homepageRevamp() ? R.xml.top_level_settings_v2 : R.xml.top_level_settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -331,12 +333,16 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi
|
||||
|
||||
@Override
|
||||
protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
|
||||
if (!mIsEmbeddingActivityEnabled || !(getActivity() instanceof SettingsHomepageActivity)) {
|
||||
return super.onCreateAdapter(preferenceScreen);
|
||||
}
|
||||
if (mIsEmbeddingActivityEnabled && (getActivity() instanceof SettingsHomepageActivity)) {
|
||||
return mHighlightMixin.onCreateAdapter(this, preferenceScreen, mScrollNeeded);
|
||||
}
|
||||
|
||||
if (Flags.homepageRevamp()) {
|
||||
return new RoundCornerPreferenceAdapter(preferenceScreen);
|
||||
}
|
||||
return super.onCreateAdapter(preferenceScreen);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Preference createPreference(Tile tile) {
|
||||
return new HomepagePreference(getPrefContext());
|
||||
@@ -376,7 +382,10 @@ public class TopLevelSettings extends DashboardFragment implements SplitLayoutLi
|
||||
}
|
||||
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider(R.xml.top_level_settings) {
|
||||
new BaseSearchIndexProvider(
|
||||
Flags.homepageRevamp()
|
||||
? R.xml.top_level_settings_v2
|
||||
: R.xml.top_level_settings) {
|
||||
|
||||
@Override
|
||||
protected boolean isPageSearchEnabled(Context context) {
|
||||
|
||||
@@ -1,62 +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.network.telephony;
|
||||
|
||||
import android.content.Context;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
|
||||
import com.android.settings.network.SubscriptionUtil;
|
||||
|
||||
/**
|
||||
* Shows information about disable a physical SIM.
|
||||
*/
|
||||
public class DisableSimFooterPreferenceController extends TelephonyBasePreferenceController {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public DisableSimFooterPreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* re-init for SIM based on given subscription ID.
|
||||
* @param subId is the given subscription ID
|
||||
*/
|
||||
public void init(int subId) {
|
||||
mSubId = subId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus(int subId) {
|
||||
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
|
||||
SubscriptionManager subManager = mContext.getSystemService(SubscriptionManager.class);
|
||||
for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mContext)) {
|
||||
if (info.getSubscriptionId() == subId) {
|
||||
if (info.isEmbedded() || SubscriptionUtil.showToggleForPhysicalSim(subManager)) {
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return AVAILABLE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT 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.telephony
|
||||
|
||||
import android.content.Context
|
||||
import android.telephony.SubscriptionManager
|
||||
|
||||
/**
|
||||
* Shows information about disable a physical SIM.
|
||||
*/
|
||||
class DisableSimFooterPreferenceController @JvmOverloads constructor(
|
||||
context: Context,
|
||||
preferenceKey: String,
|
||||
private val subscriptionRepository: SubscriptionRepository = SubscriptionRepository(context),
|
||||
) : TelephonyBasePreferenceController(context, preferenceKey) {
|
||||
|
||||
/**
|
||||
* Re-init for SIM based on given subscription ID.
|
||||
*
|
||||
* @param subId is the given subscription ID
|
||||
*/
|
||||
fun init(subId: Int) {
|
||||
mSubId = subId
|
||||
}
|
||||
|
||||
override fun getAvailabilityStatus(subId: Int): Int {
|
||||
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID ||
|
||||
subscriptionRepository.canDisablePhysicalSubscription()
|
||||
) {
|
||||
return CONDITIONALLY_UNAVAILABLE
|
||||
}
|
||||
|
||||
val isAvailable =
|
||||
subscriptionRepository.getSelectableSubscriptionInfoList().any { subInfo ->
|
||||
subInfo.subscriptionId == subId && !subInfo.isEmbedded
|
||||
}
|
||||
|
||||
return if (isAvailable) AVAILABLE else CONDITIONALLY_UNAVAILABLE
|
||||
}
|
||||
}
|
||||
@@ -48,13 +48,12 @@ import com.android.internal.telephony.flags.Flags;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.network.telephony.scan.NetworkScanRepository;
|
||||
import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanCellInfos;
|
||||
import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanComplete;
|
||||
import com.android.settings.network.telephony.scan.NetworkScanRepository.NetworkScanError;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import kotlin.Unit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -83,7 +82,8 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
private View mProgressHeader;
|
||||
private Preference mStatusMessagePreference;
|
||||
@VisibleForTesting
|
||||
List<CellInfo> mCellInfoList;
|
||||
@NonNull
|
||||
List<CellInfo> mCellInfoList = ImmutableList.of();
|
||||
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
private TelephonyManager mTelephonyManager;
|
||||
private SatelliteManager mSatelliteManager;
|
||||
@@ -96,7 +96,6 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
private AtomicBoolean mShouldFilterOutSatellitePlmn = new AtomicBoolean();
|
||||
|
||||
private NetworkScanRepository mNetworkScanRepository;
|
||||
private boolean mUpdateScanResult = false;
|
||||
|
||||
private NetworkSelectRepository mNetworkSelectRepository;
|
||||
|
||||
@@ -213,38 +212,16 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
}
|
||||
|
||||
private void launchNetworkScan() {
|
||||
setProgressBarVisible(true);
|
||||
mNetworkScanRepository.launchNetworkScan(getViewLifecycleOwner(), (networkScanResult) -> {
|
||||
if (!mUpdateScanResult) {
|
||||
// Not update UI if not in scan mode.
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
if (networkScanResult instanceof NetworkScanCellInfos networkScanCellInfos) {
|
||||
scanResultHandler(networkScanCellInfos.getCellInfos());
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
if (!isPreferenceScreenEnabled()) {
|
||||
clearPreferenceSummary();
|
||||
enablePreferenceScreen(true);
|
||||
} else if (networkScanResult instanceof NetworkScanComplete
|
||||
&& mCellInfoList == null) {
|
||||
// In case the scan timeout before getting any results
|
||||
addMessagePreference(R.string.empty_networks_list);
|
||||
} else if (networkScanResult instanceof NetworkScanError) {
|
||||
addMessagePreference(R.string.network_query_error);
|
||||
if (isPreferenceScreenEnabled()) {
|
||||
scanResultHandler(networkScanResult);
|
||||
}
|
||||
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
setProgressBarVisible(true);
|
||||
mUpdateScanResult = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update forbidden PLMNs from the USIM App
|
||||
*/
|
||||
@@ -268,8 +245,6 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
return false;
|
||||
}
|
||||
|
||||
mUpdateScanResult = false;
|
||||
|
||||
// Refresh the last selected item in case users reselect network.
|
||||
clearPreferenceSummary();
|
||||
if (mSelectedPreference != null) {
|
||||
@@ -380,27 +355,19 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
@VisibleForTesting
|
||||
protected void scanResultHandler(List<CellInfo> results) {
|
||||
mCellInfoList = filterOutSatellitePlmn(results);
|
||||
protected void scanResultHandler(NetworkScanRepository.NetworkScanResult results) {
|
||||
mCellInfoList = filterOutSatellitePlmn(results.getCellInfos());
|
||||
Log.d(TAG, "CellInfoList: " + CellInfoUtil.cellInfoListToString(mCellInfoList));
|
||||
if (mCellInfoList != null && mCellInfoList.size() != 0) {
|
||||
final NetworkOperatorPreference connectedPref = updateAllPreferenceCategory();
|
||||
if (connectedPref != null) {
|
||||
// update selected preference instance into connected preference
|
||||
if (mSelectedPreference != null) {
|
||||
mSelectedPreference = connectedPref;
|
||||
}
|
||||
} else if (!isPreferenceScreenEnabled()) {
|
||||
mSelectedPreference.setSummary(R.string.network_connecting);
|
||||
}
|
||||
enablePreferenceScreen(true);
|
||||
} else if (isPreferenceScreenEnabled()) {
|
||||
updateAllPreferenceCategory();
|
||||
NetworkScanRepository.NetworkScanState state = results.getState();
|
||||
if (state == NetworkScanRepository.NetworkScanState.ERROR) {
|
||||
addMessagePreference(R.string.network_query_error);
|
||||
} else if (mCellInfoList.isEmpty()) {
|
||||
addMessagePreference(R.string.empty_networks_list);
|
||||
// keep showing progress bar, it will be stopped when error or completed
|
||||
setProgressBarVisible(true);
|
||||
}
|
||||
// keep showing progress bar, it will be stopped when error or completed
|
||||
setProgressBarVisible(state == NetworkScanRepository.NetworkScanState.ACTIVE);
|
||||
}
|
||||
|
||||
@Keep
|
||||
@@ -417,11 +384,8 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
|
||||
/**
|
||||
* Update the content of network operators list.
|
||||
*
|
||||
* @return preference which shows connected
|
||||
*/
|
||||
@Nullable
|
||||
private NetworkOperatorPreference updateAllPreferenceCategory() {
|
||||
private void updateAllPreferenceCategory() {
|
||||
int numberOfPreferences = mPreferenceCategory.getPreferenceCount();
|
||||
|
||||
// remove unused preferences
|
||||
@@ -432,7 +396,6 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
}
|
||||
|
||||
// update the content of preference
|
||||
NetworkOperatorPreference connectedPref = null;
|
||||
for (int index = 0; index < mCellInfoList.size(); index++) {
|
||||
final CellInfo cellInfo = mCellInfoList.get(index);
|
||||
|
||||
@@ -457,23 +420,10 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
|
||||
if (mCellInfoList.get(index).isRegistered()) {
|
||||
pref.setSummary(R.string.network_connected);
|
||||
connectedPref = pref;
|
||||
} else {
|
||||
pref.setSummary(null);
|
||||
}
|
||||
}
|
||||
|
||||
// update selected preference instance by index
|
||||
for (int index = 0; index < mCellInfoList.size(); index++) {
|
||||
final CellInfo cellInfo = mCellInfoList.get(index);
|
||||
|
||||
if ((mSelectedPreference != null) && mSelectedPreference.isSameCell(cellInfo)) {
|
||||
mSelectedPreference = (NetworkOperatorPreference)
|
||||
(mPreferenceCategory.getPreference(index));
|
||||
}
|
||||
}
|
||||
|
||||
return connectedPref;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -524,13 +474,6 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isProgressBarVisible() {
|
||||
if (mProgressHeader == null) {
|
||||
return false;
|
||||
}
|
||||
return (mProgressHeader.getVisibility() == View.VISIBLE);
|
||||
}
|
||||
|
||||
protected void setProgressBarVisible(boolean visible) {
|
||||
if (mProgressHeader != null) {
|
||||
mProgressHeader.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||
@@ -538,7 +481,6 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
}
|
||||
|
||||
private void addMessagePreference(int messageId) {
|
||||
setProgressBarVisible(false);
|
||||
mStatusMessagePreference.setTitle(messageId);
|
||||
mPreferenceCategory.removeAll();
|
||||
mPreferenceCategory.addPreference(mStatusMessagePreference);
|
||||
|
||||
@@ -36,6 +36,8 @@ import kotlinx.coroutines.flow.onEach
|
||||
private const val TAG = "SubscriptionRepository"
|
||||
|
||||
class SubscriptionRepository(private val context: Context) {
|
||||
private val subscriptionManager = context.requireSubscriptionManager()
|
||||
|
||||
/**
|
||||
* Return a list of subscriptions that are available and visible to the user.
|
||||
*
|
||||
@@ -55,6 +57,7 @@ class SubscriptionRepository(private val context: Context) {
|
||||
isSubscriptionEnabledFlow(subId).collectLatestWithLifecycle(lifecycleOwner, action = action)
|
||||
}
|
||||
|
||||
fun canDisablePhysicalSubscription() = subscriptionManager.canDisablePhysicalSubscription()
|
||||
}
|
||||
|
||||
val Context.subscriptionManager: SubscriptionManager?
|
||||
|
||||
@@ -29,10 +29,12 @@ import kotlinx.coroutines.channels.ProducerScope
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
class TelephonyRepository(
|
||||
private val context: Context,
|
||||
@@ -64,19 +66,21 @@ class TelephonyRepository(
|
||||
telephonyManager.setMobileDataPolicyEnabled(policy, enabled)
|
||||
}
|
||||
|
||||
fun isDataEnabled(
|
||||
subId: Int,
|
||||
): Flow<Boolean> {
|
||||
fun isDataEnabledFlow(subId: Int): Flow<Boolean> {
|
||||
if (!SubscriptionManager.isValidSubscriptionId(subId)) return flowOf(false)
|
||||
|
||||
Log.d(TAG, "register mobileDataEnabledFlow: [$subId]")
|
||||
return context.mobileDataEnabledFlow(subId)
|
||||
.map {
|
||||
Log.d(TAG, "mobileDataEnabledFlow: receive mobile data [$subId] start")
|
||||
val telephonyManager = context.telephonyManager(subId)
|
||||
telephonyManager.isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER)
|
||||
.also { Log.d(TAG, "mobileDataEnabledFlow: [$subId] isDataEnabled(): $it") }
|
||||
}
|
||||
.catch {
|
||||
Log.w(TAG, "[$subId] isDataEnabledFlow: exception", it)
|
||||
emit(false)
|
||||
}
|
||||
.onEach { Log.d(TAG, "[$subId] isDataEnabledFlow: isDataEnabled() = $it") }
|
||||
.conflate()
|
||||
.flowOn(Dispatchers.Default)
|
||||
}
|
||||
|
||||
fun setMobileData(
|
||||
@@ -100,6 +104,7 @@ class TelephonyRepository(
|
||||
wifiPickerTrackerHelper.setCarrierNetworkEnabled(enabled)
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private const val TAG = "TelephonyRepository"
|
||||
}
|
||||
|
||||
@@ -27,25 +27,29 @@ import android.telephony.TelephonyScanManager
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import com.android.settings.R
|
||||
import com.android.settings.network.telephony.CellInfoUtil
|
||||
import com.android.settings.network.telephony.CellInfoUtil.getNetworkTitle
|
||||
import com.android.settings.network.telephony.telephonyManager
|
||||
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.asExecutor
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
class NetworkScanRepository(private val context: Context, subId: Int) {
|
||||
sealed interface NetworkScanResult
|
||||
enum class NetworkScanState {
|
||||
ACTIVE, COMPLETE, ERROR
|
||||
}
|
||||
|
||||
data class NetworkScanCellInfos(val cellInfos: List<CellInfo>) : NetworkScanResult
|
||||
data object NetworkScanComplete : NetworkScanResult
|
||||
data class NetworkScanError(val error: Int) : NetworkScanResult
|
||||
data class NetworkScanResult(
|
||||
val state: NetworkScanState,
|
||||
val cellInfos: List<CellInfo>,
|
||||
)
|
||||
|
||||
private val telephonyManager =
|
||||
context.getSystemService(TelephonyManager::class.java)!!.createForSubscriptionId(subId)
|
||||
private val telephonyManager = context.telephonyManager(subId)
|
||||
|
||||
/** TODO: Move this to UI layer, when UI layer migrated to Kotlin. */
|
||||
fun launchNetworkScan(lifecycleOwner: LifecycleOwner, onResult: (NetworkScanResult) -> Unit) {
|
||||
@@ -65,23 +69,29 @@ class NetworkScanRepository(private val context: Context, subId: Int) {
|
||||
}
|
||||
|
||||
fun networkScanFlow(): Flow<NetworkScanResult> = callbackFlow {
|
||||
var state = NetworkScanState.ACTIVE
|
||||
var cellInfos: List<CellInfo> = emptyList()
|
||||
|
||||
val callback = object : TelephonyScanManager.NetworkScanCallback() {
|
||||
override fun onResults(results: List<CellInfo>) {
|
||||
val cellInfos = results.distinctBy { CellInfoScanKey(it) }
|
||||
trySend(NetworkScanCellInfos(cellInfos))
|
||||
Log.d(TAG, "CellInfoList: ${CellInfoUtil.cellInfoListToString(cellInfos)}")
|
||||
cellInfos = results.distinctBy { CellInfoScanKey(it) }
|
||||
sendResult()
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
trySend(NetworkScanComplete)
|
||||
close()
|
||||
Log.d(TAG, "onComplete")
|
||||
state = NetworkScanState.COMPLETE
|
||||
sendResult()
|
||||
// Don't call close() here since onComplete() could happens before onResults()
|
||||
}
|
||||
|
||||
override fun onError(error: Int) {
|
||||
trySend(NetworkScanError(error))
|
||||
state = NetworkScanState.ERROR
|
||||
sendResult()
|
||||
close()
|
||||
Log.d(TAG, "onError: $error")
|
||||
}
|
||||
|
||||
private fun sendResult() {
|
||||
trySend(NetworkScanResult(state, cellInfos))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +102,7 @@ class NetworkScanRepository(private val context: Context, subId: Int) {
|
||||
)
|
||||
|
||||
awaitClose { networkScan.stopScan() }
|
||||
}.flowOn(Dispatchers.Default)
|
||||
}.conflate().onEach { Log.d(TAG, "networkScanFlow: $it") }.flowOn(Dispatchers.Default)
|
||||
|
||||
/** Create network scan for allowed network types. */
|
||||
private fun createNetworkScan(): NetworkScanRequest {
|
||||
|
||||
@@ -28,7 +28,10 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents the data class needed to create a Settings Panel. See {@link PanelFragment}.
|
||||
*
|
||||
* @deprecated this is no longer used after V and will be removed.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public interface PanelContent extends Instrumentable {
|
||||
|
||||
int VIEW_TYPE_SLIDER = 1;
|
||||
|
||||
@@ -18,7 +18,10 @@ package com.android.settings.panel;
|
||||
/**
|
||||
* PanelContentCallback provides a callback interface for {@link PanelFragment} to receive
|
||||
* events from {@link PanelContent}.
|
||||
*
|
||||
* @deprecated this is no longer used after V and will be removed.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public interface PanelContentCallback {
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settings.panel;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
public interface PanelFeatureProvider {
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,6 +27,7 @@ import androidx.annotation.Nullable;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.flags.Flags;
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
public class PanelFeatureProviderImpl implements PanelFeatureProvider {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -66,6 +66,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
public class PanelFragment extends Fragment {
|
||||
|
||||
private static final String TAG = "PanelFragment";
|
||||
@@ -519,6 +520,7 @@ public class PanelFragment extends Fragment {
|
||||
return mPanel.getViewType();
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
class LocalPanelCallback implements PanelContentCallback {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,7 +21,10 @@ package com.android.settings.panel;
|
||||
* <p>
|
||||
* Constants should only be removed if underlying panel, or use case is removed.
|
||||
* </p>
|
||||
*
|
||||
* @deprecated this is no longer used after V and will be removed.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public class PanelLoggingContract {
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,7 +48,10 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* RecyclerView adapter for Slices in Settings Panels.
|
||||
*
|
||||
* @deprecated this is no longer used after V and will be removed.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public class PanelSlicesAdapter
|
||||
extends RecyclerView.Adapter<PanelSlicesAdapter.SliceRowViewHolder> {
|
||||
|
||||
@@ -112,7 +115,10 @@ public class PanelSlicesAdapter
|
||||
|
||||
/**
|
||||
* ViewHolder for binding Slices to SliceViews.
|
||||
*
|
||||
* @deprecated this is no longer used after V and will be removed.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public class SliceRowViewHolder extends RecyclerView.ViewHolder
|
||||
implements DividerItemDecoration.DividedViewHolder {
|
||||
|
||||
|
||||
@@ -36,7 +36,10 @@ import java.util.concurrent.CountDownLatch;
|
||||
* {@link Uri}. Then check if all of the Slices have loaded with
|
||||
* {@link #isPanelReadyToLoad()}, which will return {@code true} the first time after all
|
||||
* Slices have loaded.
|
||||
*
|
||||
* @deprecated this is no longer used after V and will be removed.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public class PanelSlicesLoaderCountdownLatch {
|
||||
private final Set<Uri> mLoadedSlices;
|
||||
private final CountDownLatch mCountDownLatch;
|
||||
|
||||
@@ -42,7 +42,10 @@ import com.android.settingslib.core.lifecycle.HideNonSystemOverlayMixin;
|
||||
|
||||
/**
|
||||
* Dialog Activity to host Settings Slices.
|
||||
*
|
||||
* @deprecated this is no longer used after V and will be removed.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public class SettingsPanelActivity extends FragmentActivity {
|
||||
|
||||
private static final String TAG = "SettingsPanelActivity";
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settings.privatespace;
|
||||
import static android.app.admin.DevicePolicyManager.ACTION_SET_NEW_PASSWORD;
|
||||
|
||||
import static com.android.internal.app.SetScreenLockDialogActivity.LAUNCH_REASON_PRIVATE_SPACE_SETTINGS_ACCESS;
|
||||
import static com.android.settings.activityembedding.EmbeddedDeepLinkUtils.tryStartMultiPaneDeepLink;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.AlertDialog;
|
||||
@@ -36,11 +37,12 @@ import androidx.activity.result.ActivityResult;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.app.SetScreenLockDialogActivity;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.activityembedding.ActivityEmbeddingUtils;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settingslib.transition.SettingsTransitionHelper;
|
||||
|
||||
@@ -52,7 +54,7 @@ import com.google.android.setupdesign.util.ThemeHelper;
|
||||
* user to set a device lock if not set with an alert dialog. This can be launched using the intent
|
||||
* com.android.settings.action.OPEN_PRIVATE_SPACE_SETTINGS.
|
||||
*/
|
||||
public class PrivateSpaceAuthenticationActivity extends SettingsActivity {
|
||||
public class PrivateSpaceAuthenticationActivity extends FragmentActivity {
|
||||
private static final String TAG = "PrivateSpaceAuthCheck";
|
||||
public static final String EXTRA_SHOW_PRIVATE_SPACE_UNLOCKED =
|
||||
"extra_show_private_space_unlocked";
|
||||
@@ -76,12 +78,20 @@ public class PrivateSpaceAuthenticationActivity extends SettingsActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (isFinishing()) {
|
||||
if (!(Flags.allowPrivateProfile()
|
||||
&& android.multiuser.Flags.enablePrivateSpaceFeatures())) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = getIntent();
|
||||
String highlightMenuKey = getString(R.string.menu_key_security);
|
||||
if (shouldShowMultiPaneDeepLink(intent)
|
||||
&& tryStartMultiPaneDeepLink(this, intent, highlightMenuKey)) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Flags.allowPrivateProfile()
|
||||
&& android.multiuser.Flags.enablePrivateSpaceFeatures()) {
|
||||
ThemeHelper.trySetDynamicColor(this);
|
||||
mPrivateSpaceMaintainer =
|
||||
new Injector().injectPrivateSpaceMaintainer(getApplicationContext());
|
||||
@@ -96,9 +106,25 @@ public class PrivateSpaceAuthenticationActivity extends SettingsActivity {
|
||||
} else {
|
||||
promptToSetDeviceLock();
|
||||
}
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
|
||||
private boolean shouldShowMultiPaneDeepLink(Intent intent) {
|
||||
if (!ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the activity is task root, starting trampoline is needed in order to show two-pane UI.
|
||||
// If FLAG_ACTIVITY_NEW_TASK is set, the activity will become the start of a new task on
|
||||
// this history stack, so starting trampoline is needed in order to notify the homepage that
|
||||
// the highlight key is changed.
|
||||
if (!isTaskRoot() && (intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only starts trampoline for deep links. Should return false for all the cases that
|
||||
// Settings app starts SettingsActivity or SubSetting by itself.
|
||||
// Other apps should send deep link intent which matches intent filter of the Activity.
|
||||
return intent.getAction() != null;
|
||||
}
|
||||
|
||||
/** Starts private space setup flow or the PS settings page on device lock authentication */
|
||||
|
||||
@@ -36,11 +36,11 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.LifecycleRegistry
|
||||
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.android.settings.R
|
||||
@@ -62,7 +62,6 @@ import com.android.settingslib.spaprivileged.settingsprovider.settingsGlobalBool
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.conflate
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
@@ -207,7 +206,7 @@ fun MobileDataSectionImpl(
|
||||
}.collectAsStateWithLifecycle(initialValue = null)
|
||||
|
||||
val mobileDataStateChanged by remember(mobileDataSelectedId.intValue) {
|
||||
TelephonyRepository(context).isDataEnabled(mobileDataSelectedId.intValue)
|
||||
TelephonyRepository(context).isDataEnabledFlow(mobileDataSelectedId.intValue)
|
||||
}.collectAsStateWithLifecycle(initialValue = false)
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
|
||||
@@ -33,14 +33,12 @@ import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.defaultapps.DefaultAppPickerFragment;
|
||||
import com.android.settings.development.DeveloperOptionAwareMixin;
|
||||
import com.android.settingslib.applications.DefaultAppInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class WebViewAppPicker extends DefaultAppPickerFragment implements
|
||||
DeveloperOptionAwareMixin {
|
||||
public class WebViewAppPicker extends DefaultAppPickerFragment {
|
||||
private WebViewUpdateServiceWrapper mWebViewUpdateServiceWrapper;
|
||||
|
||||
private WebViewUpdateServiceWrapper getWebViewUpdateServiceWrapper() {
|
||||
|
||||
@@ -34,6 +34,7 @@ import androidx.window.embedding.ActivityEmbeddingController;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.homepage.SettingsHomepageActivity;
|
||||
|
||||
/**
|
||||
@@ -46,9 +47,13 @@ public class HighlightableTopLevelPreferenceAdapter extends PreferenceGroupAdapt
|
||||
|
||||
static final long DELAY_HIGHLIGHT_DURATION_MILLIS = 100L;
|
||||
private static final int RES_NORMAL_BACKGROUND =
|
||||
R.drawable.homepage_selectable_item_background;
|
||||
Flags.homepageRevamp()
|
||||
? R.drawable.homepage_selectable_item_background_v2
|
||||
: R.drawable.homepage_selectable_item_background;
|
||||
private static final int RES_HIGHLIGHTED_BACKGROUND =
|
||||
R.drawable.homepage_highlighted_item_background;
|
||||
Flags.homepageRevamp()
|
||||
? R.drawable.homepage_highlighted_item_background_v2
|
||||
: R.drawable.homepage_highlighted_item_background;
|
||||
|
||||
private final int mTitleColorNormal;
|
||||
private final int mTitleColorHighlight;
|
||||
|
||||
@@ -22,6 +22,7 @@ import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.flags.Flags;
|
||||
|
||||
/** Helper for homepage preference to manage layout. */
|
||||
public class HomepagePreferenceLayoutHelper {
|
||||
@@ -39,7 +40,10 @@ public class HomepagePreferenceLayoutHelper {
|
||||
}
|
||||
|
||||
public HomepagePreferenceLayoutHelper(Preference preference) {
|
||||
preference.setLayoutResource(R.layout.homepage_preference);
|
||||
preference.setLayoutResource(
|
||||
Flags.homepageRevamp()
|
||||
? R.layout.homepage_preference_v2
|
||||
: R.layout.homepage_preference);
|
||||
}
|
||||
|
||||
/** Sets whether the icon should be visible */
|
||||
|
||||
@@ -30,7 +30,7 @@ import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.AudioManager;
|
||||
@@ -44,7 +44,6 @@ import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.testutils.shadow.ShadowAudioManager;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settings.testutils.shadow.ShadowCachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.flags.Flags;
|
||||
|
||||
@@ -68,7 +67,7 @@ import java.util.Collection;
|
||||
public class ConnectedBluetoothDeviceUpdaterTest {
|
||||
|
||||
private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
|
||||
private static final String FAKE_EXCLUSIVE_MANAGER_NAME = "com.fake.name";
|
||||
private static final String TEST_EXCLUSIVE_MANAGER = "com.test.manager";
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
@@ -355,13 +354,16 @@ public class ConnectedBluetoothDeviceUpdaterTest {
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_notAllowedExclusiveManagedDevice_addDevice() {
|
||||
public void update_exclusivelyManagedDevice_packageNotInstalled_addDevice()
|
||||
throws Exception {
|
||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
when(mBluetoothDeviceUpdater
|
||||
.isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME.getBytes());
|
||||
TEST_EXCLUSIVE_MANAGER.getBytes());
|
||||
doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager)
|
||||
.getApplicationInfo(TEST_EXCLUSIVE_MANAGER, 0);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
@@ -370,64 +372,39 @@ public class ConnectedBluetoothDeviceUpdaterTest {
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_existingExclusivelyManagedDeviceWithPackageInstalled_removePreference()
|
||||
public void update_exclusivelyManagedDevice_packageNotEnabled_addDevice()
|
||||
throws Exception {
|
||||
final String exclusiveManagerName =
|
||||
BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME);
|
||||
ApplicationInfo appInfo = new ApplicationInfo();
|
||||
appInfo.enabled = false;
|
||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
when(mBluetoothDeviceUpdater
|
||||
.isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
exclusiveManagerName.getBytes());
|
||||
doReturn(new PackageInfo()).when(mPackageManager).getPackageInfo(exclusiveManagerName, 0);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
|
||||
verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_newExclusivelyManagedDeviceWithPackageInstalled_doNotAddPreference()
|
||||
throws Exception {
|
||||
final String exclusiveManagerName =
|
||||
BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME);
|
||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
when(mBluetoothDeviceUpdater
|
||||
.isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
exclusiveManagerName.getBytes());
|
||||
doReturn(new PackageInfo()).when(mPackageManager).getPackageInfo(exclusiveManagerName, 0);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
|
||||
verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_exclusivelyManagedDeviceWithoutPackageInstalled_addDevice()
|
||||
throws Exception {
|
||||
final String exclusiveManagerName =
|
||||
BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME);
|
||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
when(mBluetoothDeviceUpdater
|
||||
.isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
exclusiveManagerName.getBytes());
|
||||
doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager).getPackageInfo(
|
||||
exclusiveManagerName, 0);
|
||||
TEST_EXCLUSIVE_MANAGER.getBytes());
|
||||
doReturn(appInfo).when(mPackageManager).getApplicationInfo(TEST_EXCLUSIVE_MANAGER, 0);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_exclusivelyManagedDevice_packageInstalledAndEnabled_removePreference()
|
||||
throws Exception {
|
||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
when(mBluetoothDeviceUpdater
|
||||
.isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
|
||||
when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
TEST_EXCLUSIVE_MANAGER.getBytes());
|
||||
doReturn(new ApplicationInfo()).when(mPackageManager).getApplicationInfo(
|
||||
TEST_EXCLUSIVE_MANAGER, 0);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
|
||||
verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||
@@ -41,7 +41,6 @@ import android.util.Pair;
|
||||
import com.android.settings.connecteddevice.DevicePreferenceCallback;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
|
||||
import com.android.settingslib.bluetooth.BluetoothUtils;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
@@ -66,7 +65,7 @@ import java.util.List;
|
||||
public class SavedBluetoothDeviceUpdaterTest {
|
||||
|
||||
private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
|
||||
private static final String FAKE_EXCLUSIVE_MANAGER_NAME = "com.fake.name";
|
||||
private static final String TEST_EXCLUSIVE_MANAGER = "com.test.manager";
|
||||
|
||||
@Rule
|
||||
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||
@@ -339,42 +338,18 @@ public class SavedBluetoothDeviceUpdaterTest {
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_notAllowedExclusivelyManagedDevice_addDevice() {
|
||||
final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
|
||||
cachedDevices.add(mCachedBluetoothDevice);
|
||||
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
|
||||
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
|
||||
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mBluetoothDevice.isConnected()).thenReturn(false);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME.getBytes());
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_existingExclusivelyManagedDeviceWithPackageInstalled_removePreference()
|
||||
public void update_existingExclusivelyManagedDevice_packageEnabled_removePreference()
|
||||
throws Exception {
|
||||
final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
|
||||
final String exclusiveManagerName =
|
||||
BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME);
|
||||
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
|
||||
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
|
||||
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mBluetoothDevice.isConnected()).thenReturn(false);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
exclusiveManagerName.getBytes());
|
||||
|
||||
doReturn(new PackageInfo()).when(mPackageManager).getPackageInfo(exclusiveManagerName, 0);
|
||||
TEST_EXCLUSIVE_MANAGER.getBytes());
|
||||
doReturn(new ApplicationInfo()).when(mPackageManager).getApplicationInfo(
|
||||
TEST_EXCLUSIVE_MANAGER, 0);
|
||||
mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
@@ -386,23 +361,19 @@ public class SavedBluetoothDeviceUpdaterTest {
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_newExclusivelyManagedDeviceWithPackageInstalled_doNotAddPreference()
|
||||
public void update_newExclusivelyManagedDevice_packageEnabled_doNotAddPreference()
|
||||
throws Exception {
|
||||
final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
|
||||
final String exclusiveManagerName =
|
||||
BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME);
|
||||
cachedDevices.add(mCachedBluetoothDevice);
|
||||
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
|
||||
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
|
||||
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mBluetoothDevice.isConnected()).thenReturn(false);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
exclusiveManagerName.getBytes());
|
||||
|
||||
doReturn(new PackageInfo()).when(mPackageManager).getPackageInfo(exclusiveManagerName, 0);
|
||||
TEST_EXCLUSIVE_MANAGER.getBytes());
|
||||
doReturn(new ApplicationInfo()).when(mPackageManager).getApplicationInfo(
|
||||
TEST_EXCLUSIVE_MANAGER, 0);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
@@ -413,24 +384,42 @@ public class SavedBluetoothDeviceUpdaterTest {
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_exclusivelyManagedDeviceWithoutPackageInstalled_addDevice()
|
||||
public void update_exclusivelyManagedDevice_packageNotInstalled_addDevice()
|
||||
throws Exception {
|
||||
final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
|
||||
final String exclusiveManagerName =
|
||||
BluetoothUtils.getExclusiveManagers().stream().findAny().orElse(
|
||||
FAKE_EXCLUSIVE_MANAGER_NAME);
|
||||
cachedDevices.add(mCachedBluetoothDevice);
|
||||
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
|
||||
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
|
||||
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mBluetoothDevice.isConnected()).thenReturn(false);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
exclusiveManagerName.getBytes());
|
||||
TEST_EXCLUSIVE_MANAGER.getBytes());
|
||||
doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager)
|
||||
.getApplicationInfo(TEST_EXCLUSIVE_MANAGER, 0);
|
||||
|
||||
doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager).getPackageInfo(
|
||||
exclusiveManagerName, 0);
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
verify(mBluetoothDeviceUpdater).addPreference(mCachedBluetoothDevice,
|
||||
BluetoothDevicePreference.SortType.TYPE_NO_SORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_HIDE_EXCLUSIVELY_MANAGED_BLUETOOTH_DEVICE)
|
||||
public void update_exclusivelyManagedDevice_packageNotEnabled_addDevice()
|
||||
throws Exception {
|
||||
final Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
|
||||
cachedDevices.add(mCachedBluetoothDevice);
|
||||
ApplicationInfo appInfo = new ApplicationInfo();
|
||||
appInfo.enabled = false;
|
||||
when(mBluetoothAdapter.isEnabled()).thenReturn(true);
|
||||
when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mDeviceManager);
|
||||
when(mDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
|
||||
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
|
||||
when(mBluetoothDevice.isConnected()).thenReturn(false);
|
||||
when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_EXCLUSIVE_MANAGER)).thenReturn(
|
||||
TEST_EXCLUSIVE_MANAGER.getBytes());
|
||||
doReturn(appInfo).when(mPackageManager).getApplicationInfo(TEST_EXCLUSIVE_MANAGER, 0);
|
||||
|
||||
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
package com.android.settings.display;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.content.Context;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.ShortcutsSettingsFragment;
|
||||
import com.android.settings.testutils.XmlTestUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -14,15 +14,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
package com.android.settings.display;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.platform.test.annotations.DisableFlags;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.accessibility.Flags;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
@@ -31,19 +38,30 @@ import org.robolectric.RobolectricTestRunner;
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ContrastPreferenceControllerTest {
|
||||
|
||||
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
|
||||
|
||||
private static final String PREFERENCE_KEY = "preference_key";
|
||||
|
||||
private Context mContext;
|
||||
private ContrastPreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mController = new ContrastPreferenceController(ApplicationProvider.getApplicationContext(),
|
||||
PREFERENCE_KEY);
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mController = new ContrastPreferenceController(mContext, PREFERENCE_KEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_shouldReturnUnavailable() {
|
||||
@EnableFlags(Flags.FLAG_ENABLE_COLOR_CONTRAST_CONTROL)
|
||||
public void getAvailabilityStatus_flagsEnabled_shouldReturnAvailable() {
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
|
||||
.isEqualTo(BasePreferenceController.AVAILABLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisableFlags(Flags.FLAG_ENABLE_COLOR_CONTRAST_CONTROL)
|
||||
public void getAvailabilityStatus_flagsDisabled_shouldReturnUnsupported() {
|
||||
assertThat(mController.getAvailabilityStatus())
|
||||
.isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
package com.android.settings.display;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@@ -50,6 +50,7 @@ import android.widget.TextView;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -58,6 +59,7 @@ import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -84,10 +86,13 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
Locale.setDefault(new Locale("en_US"));
|
||||
org.robolectric.shadows.ShadowSettings.set24HourTimeFormat(false);
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
|
||||
final TimeZone timeZone = TimeZone.getTimeZone("UTC");
|
||||
TimeZone.setDefault(timeZone);
|
||||
DataProcessor.sTestSystemAppsPackageNames = Set.of();
|
||||
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
mContext = spy(RuntimeEnvironment.application);
|
||||
BatteryLevelData.sTestCalendar = Calendar.getInstance();
|
||||
BatteryLevelData.sTestCalendar.setTimeZone(timeZone);
|
||||
doReturn(mContext).when(mContext).getApplicationContext();
|
||||
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
|
||||
doReturn(true).when(mUserManager).isUserUnlocked(anyInt());
|
||||
@@ -115,6 +120,11 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
new BatteryEntry.NameAndIcon("fakeName", /* icon= */ null, /* iconId= */ 1));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
BatteryLevelData.sTestCalendar = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDestroy_activityIsChanging_clearBatteryEntryCache() {
|
||||
doReturn(true).when(mSettingsActivity).isChangingConfigurations();
|
||||
@@ -141,7 +151,8 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
reset(mHourlyChartView);
|
||||
setupHourlyChartViewAnimationMock();
|
||||
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
|
||||
createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 0));
|
||||
|
||||
verify(mDailyChartView, atLeastOnce()).setVisibility(View.GONE);
|
||||
// Ignore fast refresh ui from the data processor callback.
|
||||
@@ -178,7 +189,8 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
BatteryChartViewModel.AxisLabelPosition.CENTER_OF_TRAPEZOIDS,
|
||||
mBatteryChartPreferenceController.mDailyChartLabelTextGenerator);
|
||||
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
|
||||
createBatteryLevelData(/* numOfHours= */ 60, /* levelOffset= */ 0));
|
||||
|
||||
verify(mDailyChartView, atLeastOnce()).setVisibility(View.VISIBLE);
|
||||
verify(mViewPropertyAnimator, atLeastOnce()).alpha(0f);
|
||||
@@ -283,7 +295,8 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
public void onBatteryLevelDataUpdate_oneDay_showHourlyChartOnly() {
|
||||
doReturn(View.GONE).when(mHourlyChartView).getVisibility();
|
||||
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
|
||||
createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 0));
|
||||
|
||||
verify(mChartSummaryTextView).setVisibility(View.VISIBLE);
|
||||
verify(mDailyChartView).setVisibility(View.GONE);
|
||||
@@ -295,7 +308,8 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
doReturn(View.GONE).when(mHourlyChartView).getVisibility();
|
||||
|
||||
mBatteryChartPreferenceController.mDailyChartIndex = SELECTED_INDEX_ALL;
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
|
||||
createBatteryLevelData(/* numOfHours= */ 60, /* levelOffset= */ 0));
|
||||
|
||||
verify(mChartSummaryTextView).setVisibility(View.VISIBLE);
|
||||
verify(mDailyChartView).setVisibility(View.VISIBLE);
|
||||
@@ -307,7 +321,8 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
doReturn(View.GONE).when(mHourlyChartView).getVisibility();
|
||||
|
||||
mBatteryChartPreferenceController.mDailyChartIndex = 0;
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
|
||||
createBatteryLevelData(/* numOfHours= */ 60, /* levelOffset= */ 0));
|
||||
|
||||
verify(mChartSummaryTextView).setVisibility(View.VISIBLE);
|
||||
verify(mDailyChartView).setVisibility(View.VISIBLE);
|
||||
@@ -379,7 +394,8 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void selectedSlotText_selectAllDaysAllHours_returnNull() {
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
|
||||
createBatteryLevelData(/* numOfHours= */ 60, /* levelOffset= */ 0));
|
||||
mBatteryChartPreferenceController.mDailyChartIndex = SELECTED_INDEX_ALL;
|
||||
mBatteryChartPreferenceController.mHourlyChartIndex = SELECTED_INDEX_ALL;
|
||||
|
||||
@@ -390,7 +406,8 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void selectedSlotText_onlyOneDayDataSelectAllHours_returnNull() {
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
|
||||
createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 0));
|
||||
mBatteryChartPreferenceController.mDailyChartIndex = 0;
|
||||
mBatteryChartPreferenceController.mHourlyChartIndex = SELECTED_INDEX_ALL;
|
||||
|
||||
@@ -401,7 +418,8 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void selectedSlotText_selectADayAllHours_onlyDayText() {
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
|
||||
createBatteryLevelData(/* numOfHours= */ 60, /* levelOffset= */ 0));
|
||||
mBatteryChartPreferenceController.mDailyChartIndex = 1;
|
||||
mBatteryChartPreferenceController.mHourlyChartIndex = SELECTED_INDEX_ALL;
|
||||
|
||||
@@ -412,7 +430,8 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void selectedSlotText_onlyOneDayDataSelectAnHour_onlyHourText() {
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
|
||||
createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 0));
|
||||
mBatteryChartPreferenceController.mDailyChartIndex = 0;
|
||||
mBatteryChartPreferenceController.mHourlyChartIndex = 2;
|
||||
|
||||
@@ -426,7 +445,8 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void selectedSlotText_SelectADayAnHour_dayAndHourText() {
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(60));
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
|
||||
createBatteryLevelData(/* numOfHours= */ 60, /* levelOffset= */ 0));
|
||||
mBatteryChartPreferenceController.mDailyChartIndex = 1;
|
||||
mBatteryChartPreferenceController.mHourlyChartIndex = 8;
|
||||
|
||||
@@ -439,8 +459,9 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectedSlotText_selectFirstSlot_withMinuteText() {
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
|
||||
public void selectedSlotText_selectFirstSlotAfterFullCharged_withMinuteText() {
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
|
||||
createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 0));
|
||||
mBatteryChartPreferenceController.mDailyChartIndex = 0;
|
||||
mBatteryChartPreferenceController.mHourlyChartIndex = 0;
|
||||
|
||||
@@ -452,9 +473,29 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
.isEqualTo("Battery level percentage from 100% to 99%");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectedSlotText_selectFirstSlotAfterTimeUpdated_withMinuteText() {
|
||||
BatteryLevelData batteryLevelData =
|
||||
createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 10);
|
||||
assertThat(batteryLevelData.getHourlyBatteryLevelsPerDay().get(0).isStartTimestamp())
|
||||
.isTrue();
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
|
||||
createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 10));
|
||||
mBatteryChartPreferenceController.mDailyChartIndex = 0;
|
||||
mBatteryChartPreferenceController.mHourlyChartIndex = 0;
|
||||
|
||||
assertThat(mBatteryChartPreferenceController.getSlotInformation(false))
|
||||
.isEqualTo("7:01 AM - 8 AM");
|
||||
assertThat(mBatteryChartPreferenceController.getSlotInformation(true))
|
||||
.isEqualTo("7:01 AM to 8 AM");
|
||||
assertThat(mBatteryChartPreferenceController.getBatteryLevelPercentageInfo())
|
||||
.isEqualTo("Battery level percentage from 90% to 89%");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectedSlotText_selectLastSlot_withNowText() {
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(6));
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
|
||||
createBatteryLevelData(/* numOfHours= */ 6, /* levelOffset= */ 0));
|
||||
mBatteryChartPreferenceController.mDailyChartIndex = 0;
|
||||
mBatteryChartPreferenceController.mHourlyChartIndex = 3;
|
||||
|
||||
@@ -468,7 +509,8 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void selectedSlotText_selectOnlySlot_withMinuteAndNowText() {
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(1));
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
|
||||
createBatteryLevelData(/* numOfHours= */ 1, /* levelOffset= */ 0));
|
||||
mBatteryChartPreferenceController.mDailyChartIndex = 0;
|
||||
mBatteryChartPreferenceController.mHourlyChartIndex = 0;
|
||||
|
||||
@@ -493,7 +535,8 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
mBatteryChartPreferenceController.mHourlyChartIndex = -1;
|
||||
|
||||
mBatteryChartPreferenceController.onCreate(bundle);
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(createBatteryLevelData(25));
|
||||
mBatteryChartPreferenceController.onBatteryLevelDataUpdate(
|
||||
createBatteryLevelData(/* numOfHours= */ 25, /* levelOffset= */ 0));
|
||||
|
||||
assertThat(mBatteryChartPreferenceController.mDailyChartIndex)
|
||||
.isEqualTo(expectedDailyIndex);
|
||||
@@ -503,7 +546,8 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void getTotalHours_getExpectedResult() {
|
||||
BatteryLevelData batteryLevelData = createBatteryLevelData(60);
|
||||
BatteryLevelData batteryLevelData =
|
||||
createBatteryLevelData(/* numOfHours= */ 60, /* levelOffset= */ 0);
|
||||
|
||||
final int totalHour = BatteryChartPreferenceController.getTotalHours(batteryLevelData);
|
||||
|
||||
@@ -516,10 +560,10 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS;
|
||||
}
|
||||
|
||||
private static BatteryLevelData createBatteryLevelData(int numOfHours) {
|
||||
private static BatteryLevelData createBatteryLevelData(int numOfHours, int levelOffset) {
|
||||
Map<Long, Integer> batteryLevelMap = new ArrayMap<>();
|
||||
for (int index = 0; index < numOfHours; index += 2) {
|
||||
final Integer level = 100 - index;
|
||||
final Integer level = 100 - index - levelOffset;
|
||||
Long timestamp = generateTimestamp(index);
|
||||
if (index == 0) {
|
||||
timestamp += DateUtils.MINUTE_IN_MILLIS;
|
||||
@@ -529,6 +573,8 @@ public final class BatteryChartPreferenceControllerTest {
|
||||
}
|
||||
long current = generateTimestamp(numOfHours - 1) + DateUtils.MINUTE_IN_MILLIS * 2;
|
||||
batteryLevelMap.put(current, 66);
|
||||
|
||||
BatteryLevelData.sTestCalendar.setTimeInMillis(current);
|
||||
DataProcessor.sTestCurrentTimeMillis = current;
|
||||
return new BatteryLevelData(batteryLevelMap);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ import com.android.settings.testutils.BatteryTestUtils;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
@@ -64,9 +63,8 @@ public final class BootBroadcastReceiverTest {
|
||||
|
||||
// Inserts fake data into database for testing.
|
||||
final BatteryStateDatabase database = BatteryTestUtils.setUpBatteryStateDatabase(mContext);
|
||||
BatteryTestUtils.insertDataToBatteryStateTable(
|
||||
mContext, Clock.systemUTC().millis(), "com.android.systemui");
|
||||
mDao = database.batteryStateDao();
|
||||
mDao.clearAll();
|
||||
clearSharedPreferences();
|
||||
}
|
||||
|
||||
@@ -129,10 +127,13 @@ public final class BootBroadcastReceiverTest {
|
||||
assertThat(mShadowAlarmManager.peekNextScheduledAlarm()).isNull();
|
||||
}
|
||||
|
||||
@Ignore("b/314921894")
|
||||
@Test
|
||||
public void onReceive_withTimeChangedIntent_clearsAllDataAndRefreshesJob()
|
||||
public void onReceive_withTimeChangedIntentSetEarlierTime_refreshesJob()
|
||||
throws InterruptedException {
|
||||
BatteryTestUtils.insertDataToBatteryStateTable(
|
||||
mContext, Clock.systemUTC().millis() + 60000, "com.android.systemui");
|
||||
assertThat(mDao.getAllAfter(0).size()).isEqualTo(1);
|
||||
|
||||
mReceiver.onReceive(mContext, new Intent(Intent.ACTION_TIME_CHANGED));
|
||||
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
@@ -140,6 +141,52 @@ public final class BootBroadcastReceiverTest {
|
||||
assertThat(mShadowAlarmManager.peekNextScheduledAlarm()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onReceive_withTimeChangedIntentSetLaterTime_clearNoDataAndRefreshesJob()
|
||||
throws InterruptedException {
|
||||
BatteryTestUtils.insertDataToBatteryStateTable(
|
||||
mContext, Clock.systemUTC().millis() - 60000, "com.android.systemui");
|
||||
assertThat(mDao.getAllAfter(0).size()).isEqualTo(1);
|
||||
|
||||
mReceiver.onReceive(mContext, new Intent(Intent.ACTION_TIME_CHANGED));
|
||||
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
assertThat(mDao.getAllAfter(0).size()).isEqualTo(1);
|
||||
assertThat(mShadowAlarmManager.peekNextScheduledAlarm()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onReceive_withTimeFormatChangedIntent_skipRefreshJob() throws InterruptedException {
|
||||
BatteryTestUtils.insertDataToBatteryStateTable(
|
||||
mContext, Clock.systemUTC().millis() + 60000, "com.android.systemui");
|
||||
assertThat(mDao.getAllAfter(0).size()).isEqualTo(1);
|
||||
|
||||
mReceiver.onReceive(
|
||||
mContext,
|
||||
new Intent(Intent.EXTRA_INTENT)
|
||||
.putExtra(
|
||||
Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT,
|
||||
Intent.EXTRA_TIME_PREF_VALUE_USE_12_HOUR));
|
||||
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
assertThat(mDao.getAllAfter(0).size()).isEqualTo(1);
|
||||
assertThat(mShadowAlarmManager.peekNextScheduledAlarm()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onReceive_withTimeZoneChangedIntent_clearAllDataAndRefreshesJob()
|
||||
throws InterruptedException {
|
||||
BatteryTestUtils.insertDataToBatteryStateTable(
|
||||
mContext, Clock.systemUTC().millis(), "com.android.systemui");
|
||||
assertThat(mDao.getAllAfter(0).size()).isEqualTo(1);
|
||||
|
||||
mReceiver.onReceive(mContext, new Intent(Intent.ACTION_TIMEZONE_CHANGED));
|
||||
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
assertThat(mDao.getAllAfter(0)).isEmpty();
|
||||
assertThat(mShadowAlarmManager.peekNextScheduledAlarm()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invokeJobRecheck_broadcastsIntent() {
|
||||
BootBroadcastReceiver.invokeJobRecheck(mContext);
|
||||
|
||||
@@ -170,7 +170,8 @@ public final class DataProcessManagerTest {
|
||||
final Map<Long, Integer> batteryLevelMap1 =
|
||||
Map.of(timestamps1.get(0), 100, timestamps1.get(1), 100, timestamps1.get(2), 100);
|
||||
hourlyBatteryLevelsPerDay.add(
|
||||
new BatteryLevelData.PeriodBatteryLevelData(batteryLevelMap1, timestamps1));
|
||||
new BatteryLevelData.PeriodBatteryLevelData(
|
||||
batteryLevelMap1, timestamps1, /* isStartTimestamp= */ false));
|
||||
// Adds the day 2 data.
|
||||
hourlyBatteryLevelsPerDay.add(null);
|
||||
// Adds the day 3 data.
|
||||
@@ -178,7 +179,8 @@ public final class DataProcessManagerTest {
|
||||
final Map<Long, Integer> batteryLevelMap2 =
|
||||
Map.of(timestamps2.get(0), 100, timestamps2.get(1), 100);
|
||||
hourlyBatteryLevelsPerDay.add(
|
||||
new BatteryLevelData.PeriodBatteryLevelData(batteryLevelMap2, timestamps2));
|
||||
new BatteryLevelData.PeriodBatteryLevelData(
|
||||
batteryLevelMap2, timestamps2, /* isStartTimestamp= */ false));
|
||||
// Fake current usage data.
|
||||
final UsageEvents.Event event1 =
|
||||
getUsageEvent(UsageEvents.Event.ACTIVITY_RESUMED, /* timestamp= */ 1, packageName);
|
||||
|
||||
@@ -209,7 +209,8 @@ public final class DataProcessorTest {
|
||||
final Map<Long, Integer> batteryLevelMap1 =
|
||||
Map.of(timestamps1.get(0), 100, timestamps1.get(1), 100, timestamps1.get(2), 100);
|
||||
hourlyBatteryLevelsPerDay.add(
|
||||
new BatteryLevelData.PeriodBatteryLevelData(batteryLevelMap1, timestamps1));
|
||||
new BatteryLevelData.PeriodBatteryLevelData(
|
||||
batteryLevelMap1, timestamps1, /* isStartTimestamp= */ false));
|
||||
// Adds the day 2 data.
|
||||
hourlyBatteryLevelsPerDay.add(null);
|
||||
// Adds the day 3 data.
|
||||
@@ -217,7 +218,8 @@ public final class DataProcessorTest {
|
||||
final Map<Long, Integer> batteryLevelMap2 =
|
||||
Map.of(timestamps2.get(0), 100, timestamps2.get(1), 100);
|
||||
hourlyBatteryLevelsPerDay.add(
|
||||
new BatteryLevelData.PeriodBatteryLevelData(batteryLevelMap2, timestamps2));
|
||||
new BatteryLevelData.PeriodBatteryLevelData(
|
||||
batteryLevelMap2, timestamps2, /* isStartTimestamp= */ false));
|
||||
final List<AppUsageEvent> appUsageEventList = new ArrayList<>();
|
||||
// Adds some events before the start timestamp.
|
||||
appUsageEventList.add(
|
||||
@@ -365,7 +367,8 @@ public final class DataProcessorTest {
|
||||
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
|
||||
new ArrayList<>();
|
||||
hourlyBatteryLevelsPerDay.add(
|
||||
new BatteryLevelData.PeriodBatteryLevelData(new ArrayMap<>(), new ArrayList<>()));
|
||||
new BatteryLevelData.PeriodBatteryLevelData(
|
||||
new ArrayMap<>(), new ArrayList<>(), /* isStartTimestamp= */ false));
|
||||
assertThat(
|
||||
DataProcessor.generateAppUsagePeriodMap(
|
||||
mContext,
|
||||
@@ -858,7 +861,8 @@ public final class DataProcessorTest {
|
||||
new ArrayList<>();
|
||||
|
||||
hourlyBatteryLevelsPerDay.add(
|
||||
new BatteryLevelData.PeriodBatteryLevelData(new ArrayMap<>(), new ArrayList<>()));
|
||||
new BatteryLevelData.PeriodBatteryLevelData(
|
||||
new ArrayMap<>(), new ArrayList<>(), /* isStartTimestamp= */ false));
|
||||
|
||||
assertThat(
|
||||
DataProcessor.getBatteryDiffDataMap(
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.settings.homepage;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.nullable;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
@@ -59,11 +57,6 @@ public class TopLevelSettingsTest {
|
||||
mSettings.onAttach(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldForceRoundedIcon_true() {
|
||||
assertThat(mSettings.shouldForceRoundedIcon()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onCreatePreferences_shouldTintPreferenceIcon() {
|
||||
final Preference preference = new Preference(mContext);
|
||||
|
||||
@@ -29,7 +29,10 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* Fake PanelContent for testing.
|
||||
*
|
||||
* @deprecated this is no longer used after V and will be removed.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public class FakePanelContent implements PanelContent {
|
||||
|
||||
public static final String FAKE_ACTION = "fake_action";
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.settings.panel;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
public class FakeSettingsPanelActivity extends SettingsPanelActivity {
|
||||
@Override
|
||||
public ComponentName getCallingActivity() {
|
||||
|
||||
@@ -54,6 +54,7 @@ import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
@Ignore("b/313576125")
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user