Snap for 7266202 from ec7c17c3cd to sc-release

Change-Id: Idef03e1f10b449697a7b39ec20d1cb02ddc1826f
This commit is contained in:
android-build-team Robot
2021-04-08 01:08:21 +00:00
50 changed files with 1318 additions and 577 deletions

View File

@@ -1,50 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="77dp"
android:height="134dp"
android:viewportWidth="77"
android:viewportHeight="134">
<path
android:pathData="M7.4,1.1L69.6,1.1A6.3,6.3 0,0 1,75.9 7.4L75.9,126.6A6.3,6.3 0,0 1,69.6 132.9L7.4,132.9A6.3,6.3 0,0 1,1.1 126.6L1.1,7.4A6.3,6.3 0,0 1,7.4 1.1z"
android:strokeWidth="1.8"
android:fillColor="#F2F3F4"
android:strokeColor="#DADCE0"/>
<group>
<clip-path
android:pathData="M7.4,1.1L69.6,1.1A6.3,6.3 0,0 1,75.9 7.4L75.9,126.6A6.3,6.3 0,0 1,69.6 132.9L7.4,132.9A6.3,6.3 0,0 1,1.1 126.6L1.1,7.4A6.3,6.3 0,0 1,7.4 1.1z"/>
<path
android:pathData="M10.442,4.948L67.167,4.948A5.4,5.4 0,0 1,72.567 10.348L72.567,123.548A5.4,5.4 0,0 1,67.167 128.948L10.442,128.948A5.4,5.4 0,0 1,5.042 123.548L5.042,10.348A5.4,5.4 0,0 1,10.442 4.948z"
android:fillColor="#ffffff"/>
<group>
<clip-path
android:pathData="M10.442,4.948L67.167,4.948A5.4,5.4 0,0 1,72.567 10.348L72.567,123.548A5.4,5.4 0,0 1,67.167 128.948L10.442,128.948A5.4,5.4 0,0 1,5.042 123.548L5.042,10.348A5.4,5.4 0,0 1,10.442 4.948z"/>
<path
android:pathData="M13,5L65,5A8,8 0,0 1,73 13L73,120A8,8 0,0 1,65 128L13,128A8,8 0,0 1,5 120L5,13A8,8 0,0 1,13 5z"
android:strokeLineJoin="bevel"
android:strokeWidth="10"
android:fillColor="#00000000"
android:strokeColor="#F29900"/>
<path
android:pathData="M51.077,14V18.314H56.612L50,24.958L53.037,28L59.692,21.334V26.921H64V14H51.077Z"
android:fillColor="#F29900"/>
<path
android:pathData="M25.963,104L19.308,110.655V105.077H15V118H27.923V113.692H22.366L29,107.037L25.963,104Z"
android:fillColor="#F29900"/>
</group>
</group>
</vector>

View File

@@ -1,52 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="77dp"
android:height="134dp"
android:viewportWidth="77"
android:viewportHeight="134">
<path
android:pathData="M7.4,1.1L69.6,1.1A6.3,6.3 0,0 1,75.9 7.4L75.9,126.6A6.3,6.3 0,0 1,69.6 132.9L7.4,132.9A6.3,6.3 0,0 1,1.1 126.6L1.1,7.4A6.3,6.3 0,0 1,7.4 1.1z"
android:strokeWidth="1.8"
android:fillColor="#F2F3F4"
android:strokeColor="#DADCE0"/>
<group>
<clip-path
android:pathData="M7.4,1.1L69.6,1.1A6.3,6.3 0,0 1,75.9 7.4L75.9,126.6A6.3,6.3 0,0 1,69.6 132.9L7.4,132.9A6.3,6.3 0,0 1,1.1 126.6L1.1,7.4A6.3,6.3 0,0 1,7.4 1.1z"/>
<path
android:pathData="M10.442,4.948L67.167,4.948A5.4,5.4 0,0 1,72.567 10.348L72.567,123.548A5.4,5.4 0,0 1,67.167 128.948L10.442,128.948A5.4,5.4 0,0 1,5.042 123.548L5.042,10.348A5.4,5.4 0,0 1,10.442 4.948z"
android:fillColor="#ffffff"/>
<group>
<clip-path
android:pathData="M10.442,4.948L67.167,4.948A5.4,5.4 0,0 1,72.567 10.348L72.567,123.548A5.4,5.4 0,0 1,67.167 128.948L10.442,128.948A5.4,5.4 0,0 1,5.042 123.548L5.042,10.348A5.4,5.4 0,0 1,10.442 4.948z"/>
<path
android:pathData="M39,94h24v24h-24z"
android:fillColor="#000000"
android:fillAlpha="0.7"/>
<path
android:pathData="M51.414,98.138H45.138C44.033,98.138 43.138,99.033 43.138,100.138V112.689C43.138,113.794 44.033,114.689 45.138,114.689H57.69C58.794,114.689 59.69,113.794 59.69,112.689L59.69,106.414H57.69L57.69,112.689L45.138,112.689V100.138H51.414V98.138ZM49.414,108.414H48.448V109.379H49.414V108.414ZM48.448,106.414H46.448V108.414V109.379V111.379H48.448H49.414H51.414V109.379V108.414V106.414H49.414H48.448ZM55.891,103.103L58.035,103.103V104.758L53.069,104.758V99.793L54.724,99.793V101.936L58.275,98.378L59.45,99.553L55.891,103.103Z"
android:fillColor="#ffffff"
android:fillType="evenOdd"/>
<path
android:pathData="M13,5L65,5A8,8 0,0 1,73 13L73,120A8,8 0,0 1,65 128L13,128A8,8 0,0 1,5 120L5,13A8,8 0,0 1,13 5z"
android:strokeLineJoin="bevel"
android:strokeWidth="10"
android:fillColor="#00000000"
android:strokeColor="#F29900"/>
</group>
</group>
</vector>

View File

@@ -1,50 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="77dp"
android:height="134dp"
android:viewportWidth="77"
android:viewportHeight="134">
<path
android:pathData="M7.4,1.1L69.6,1.1A6.3,6.3 0,0 1,75.9 7.4L75.9,126.6A6.3,6.3 0,0 1,69.6 132.9L7.4,132.9A6.3,6.3 0,0 1,1.1 126.6L1.1,7.4A6.3,6.3 0,0 1,7.4 1.1z"
android:strokeWidth="1.8"
android:fillColor="#F2F3F4"
android:strokeColor="#DADCE0"/>
<group>
<clip-path
android:pathData="M7.4,1.1L69.6,1.1A6.3,6.3 0,0 1,75.9 7.4L75.9,126.6A6.3,6.3 0,0 1,69.6 132.9L7.4,132.9A6.3,6.3 0,0 1,1.1 126.6L1.1,7.4A6.3,6.3 0,0 1,7.4 1.1z"/>
<path
android:pathData="M10.442,4.948L67.167,4.948A5.4,5.4 0,0 1,72.567 10.348L72.567,123.548A5.4,5.4 0,0 1,67.167 128.948L10.442,128.948A5.4,5.4 0,0 1,5.042 123.548L5.042,10.348A5.4,5.4 0,0 1,10.442 4.948z"
android:fillColor="#ffffff"/>
<group>
<clip-path
android:pathData="M10.442,4.948L67.167,4.948A5.4,5.4 0,0 1,72.567 10.348L72.567,123.548A5.4,5.4 0,0 1,67.167 128.948L10.442,128.948A5.4,5.4 0,0 1,5.042 123.548L5.042,10.348A5.4,5.4 0,0 1,10.442 4.948z"/>
<path
android:pathData="M15,47L64,47A2,2 0,0 1,66 49L66,84A2,2 0,0 1,64 86L15,86A2,2 0,0 1,13 84L13,49A2,2 0,0 1,15 47z"
android:strokeLineJoin="bevel"
android:strokeWidth="5"
android:fillColor="#00000000"
android:strokeColor="#F29900"/>
<path
android:pathData="M47.077,53V57.314H52.612L46,63.958L49.037,67L55.692,60.334V65.921H60V53H47.077Z"
android:fillColor="#F29900"/>
<path
android:pathData="M29.963,66L23.308,72.655V67.077H19V80H31.923V75.692H26.366L33,69.037L29.963,66Z"
android:fillColor="#F29900"/>
</group>
</group>
</vector>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="77dp"
android:height="134dp"
android:viewportWidth="77"
android:viewportHeight="134">
<path
android:pathData="M69.6,1.1H7.4C3.921,1.1 1.1,3.921 1.1,7.4V126.6C1.1,130.079 3.921,132.9 7.4,132.9H69.6C73.079,132.9 75.9,130.079 75.9,126.6V7.4C75.9,3.921 73.079,1.1 69.6,1.1Z"
android:strokeWidth="1.8"
android:fillColor="#F2F3F4"
android:strokeColor="#DADCE0"/>
<path
android:pathData="M66.642,5H10.358C7.399,5 5,7.418 5,10.4V123.6C5,126.582 7.399,129 10.358,129H66.642C69.601,129 72,126.582 72,123.6V10.4C72,7.418 69.601,5 66.642,5Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M66,10H11C10.448,10 10,10.448 10,11V123C10,123.552 10.448,124 11,124H66C66.552,124 67,123.552 67,123V11C67,10.448 66.552,10 66,10ZM11,5C7.686,5 5,7.686 5,11V123C5,126.314 7.686,129 11,129H66C69.314,129 72,126.314 72,123V11C72,7.686 69.314,5 66,5H11Z"
android:fillColor="#F29900"
android:fillType="evenOdd"/>
<path
android:pathData="M49.077,15V19.314H54.612L48,25.958L51.037,29L57.692,22.334V27.921H62V15H49.077Z"
android:fillColor="#F29900"/>
<path
android:pathData="M25.963,105L19.308,111.655V106.077H15V119H27.923V114.692H22.366L29,108.037L25.963,105Z"
android:fillColor="#F29900"/>
</vector>

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="77dp"
android:height="134dp"
android:viewportWidth="77"
android:viewportHeight="134">
<path
android:pathData="M69.6,1.1H7.4C3.921,1.1 1.1,3.921 1.1,7.4V126.6C1.1,130.079 3.921,132.9 7.4,132.9H69.6C73.079,132.9 75.9,130.079 75.9,126.6V7.4C75.9,3.921 73.079,1.1 69.6,1.1Z"
android:strokeWidth="1.8"
android:fillColor="#F2F3F4"
android:strokeColor="#DADCE0"/>
<path
android:pathData="M66.642,5H10.358C7.399,5 5,7.418 5,10.4V123.6C5,126.582 7.399,129 10.358,129H66.642C69.601,129 72,126.582 72,123.6V10.4C72,7.418 69.601,5 66.642,5Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M63,94H39V118H63V94Z"
android:fillColor="#000000"
android:fillAlpha="0.7"/>
<path
android:pathData="M43,106V114H59V98H51V99.6H57.4V112.4H44.6V106H43Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M49.4,98H43V104.4H49.4V98Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M55.8,105.2V106.8H52.928L56.56,110.432L55.432,111.56L51.8,107.928V110.8H50.2V105.2H55.8Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M66,10H11C10.448,10 10,10.448 10,11V123C10,123.552 10.448,124 11,124H66C66.552,124 67,123.552 67,123V11C67,10.448 66.552,10 66,10ZM11,5C7.686,5 5,7.686 5,11V123C5,126.314 7.686,129 11,129H66C69.314,129 72,126.314 72,123V11C72,7.686 69.314,5 66,5H11Z"
android:fillColor="#F29900"
android:fillType="evenOdd"/>
</vector>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="77dp"
android:height="134dp"
android:viewportWidth="77"
android:viewportHeight="134">
<path
android:pathData="M69.6,1.1H7.4C3.921,1.1 1.1,3.921 1.1,7.4V126.6C1.1,130.079 3.921,132.9 7.4,132.9H69.6C73.079,132.9 75.9,130.079 75.9,126.6V7.4C75.9,3.921 73.079,1.1 69.6,1.1Z"
android:strokeWidth="1.8"
android:fillColor="#F2F3F4"
android:strokeColor="#DADCE0"/>
<path
android:pathData="M66.642,5H10.358C7.399,5 5,7.418 5,10.4V123.6C5,126.582 7.399,129 10.358,129H66.642C69.601,129 72,126.582 72,123.6V10.4C72,7.418 69.601,5 66.642,5Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M63,48H14C12.895,48 12,48.895 12,50V85C12,86.105 12.895,87 14,87H63C64.105,87 65,86.105 65,85V50C65,48.895 64.105,48 63,48Z"
android:strokeLineJoin="bevel"
android:strokeWidth="5"
android:fillColor="#00000000"
android:strokeColor="#F29900"/>
<path
android:pathData="M46.077,54V58.314H51.612L45,64.958L48.037,68L54.692,61.334V66.921H59V54H46.077Z"
android:fillColor="#F29900"/>
<path
android:pathData="M28.963,67L22.308,73.655V68.077H18V81H30.923V76.692H25.366L32,70.037L28.963,67Z"
android:fillColor="#F29900"/>
</vector>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
<!-- Copyright (C) 2021 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -18,36 +18,25 @@
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingStart="@dimen/preference_no_icon_padding_start"
android:paddingStart="?android:attr/listPreferredItemPaddingEnd"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:orientation="vertical">
<TextView
android:id="@+id/charge"
android:id="@+id/chart_summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:fontFamily="@*android:string/config_headlineFontFamily"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="36sp"
android:textColor="?android:attr/colorAccent" />
android:layout_marginBottom="45dp"
android:textAppearance="?android:attr/textAppearanceSmall"
settings:textColor="?android:attr/textColorSecondary"
android:text="@string/battery_usage_chart_graph_hint" />
<com.android.settings.widget.UsageView
android:id="@+id/battery_usage"
<com.android.settings.fuelgauge.BatteryChartView
android:id="@+id/battery_chart"
android:layout_width="match_parent"
android:layout_height="141dp"
android:layout_marginBottom="16dp"
settings:sideLabels="@array/battery_labels"
android:colorAccent="?android:attr/colorAccent"
android:gravity="end"
android:textAppearance="?android:attr/textAppearanceSmall"
settings:textColor="?android:attr/textColorSecondary" />
<TextView
android:id="@+id/bottom_summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>

View File

@@ -15,25 +15,26 @@
limitations under the License.
-->
<RelativeLayout
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="true"
android:clipChildren="true"
android:orientation="vertical">
android:clipChildren="true">
<include
android:id="@+id/wifi_dialog_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/add_network_button_bar"
android:layout_alignParentTop="true"
app:layout_constraintTop_toTopOf="parent"
layout="@layout/wifi_dialog"/>
<include
android:id="@+id/add_network_button_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
app:layout_constraintTop_toBottomOf="@id/wifi_dialog_frame"
layout="@*android:layout/alert_dialog_button_bar_material"/>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -446,4 +446,11 @@
<!-- Choose SIM Activity dimens -->
<dimen name="subtitle_bottom_padding">24dp</dimen>
<!-- Battery usage chart view component -->
<dimen name="chartview_divider_width">1dp</dimen>
<dimen name="chartview_divider_height">4dp</dimen>
<dimen name="chartview_trapezoid_radius">2dp</dimen>
<dimen name="chartview_trapezoid_margin_start">1dp</dimen>
<dimen name="chartview_trapezoid_margin_bottom">2dp</dimen>
</resources>

View File

@@ -2508,9 +2508,11 @@
<!-- Summary for the toggle to turn off hotspot automatically [CHAR LIMIT=NONE]-->
<string name="wifi_hotspot_auto_off_summary">When no devices are connected</string>
<!-- Title for the toggle to enable/disable the maximize compatibility [CHAR LIMIT=NONE]-->
<string name="wifi_hotspot_maximize_compatibility">Maximize compatibility</string>
<!-- Summary for the toggle to show the maximize compatibility warning message [CHAR LIMIT=NONE]-->
<string name="wifi_hotspot_maximize_compatibility_summary">This may reduce speed for devices connected to this hotspot and use more power</string>
<string name="wifi_hotspot_maximize_compatibility">Extend compatibility</string>
<!-- Summary for the toggle to show the maximize compatibility warning message in single AP device [CHAR LIMIT=NONE]-->
<string name="wifi_hotspot_maximize_compatibility_single_ap_summary">Helps other devices find this hotspot. Reduces hotspot connection speed.</string>
<!-- Summary for the toggle to show the maximize compatibility warning message in dual AP device [CHAR LIMIT=NONE]-->
<string name="wifi_hotspot_maximize_compatibility_dual_ap_summary">Helps other devices find this hotspot. Increases battery usage.</string>
<!-- Summary text when turning hotspot on -->
<string name="wifi_tether_starting">Turning hotspot on\u2026</string>
@@ -2942,6 +2944,10 @@
<string name="adaptive_sleep_contextual_slice_title">Turn on screen attention</string>
<!-- Description about the contextual adaptive sleep card [CHAR LIMIT=NONE]-->
<string name="adaptive_sleep_contextual_slice_summary">Keep screen on when looking at it</string>
<!-- auto_rotate settings screen, title about the camera privacy lock enabled [CHAR LIMIT=NONE]-->
<string name="auto_rotate_camera_lock_title">Camera is locked</string>
<!-- Description feature's privacy sensitive details to make sure users understand what feature users, what it saves/sends etc [CHAR LIMIT=NONE]-->
<string name="auto_rotate_camera_lock_summary">Camera must be unlocked for Face Detection</string>
<!-- auto_rotate settings screen, title about the required permission is missing [CHAR LIMIT=NONE]-->
<string name="auto_rotate_summary_no_permission">Camera access is required for Face Detection. Tap to manage permissions for Device Personalization Services</string>
<!-- auto_rotate settings screen, text for the camera permission button [CHAR LIMIT=NONE]-->
@@ -6348,6 +6354,21 @@
<!-- [CHAR_LIMIT=NONE] Battery percentage: Description for preference -->
<string name="battery_percentage_description">Show battery percentage in status bar</string>
<!-- [CHAR_LIMIT=NONE] Battery usage main screen chart graph hint -->
<string name="battery_usage_chart_graph_hint">Battery level for past 24 hr</string>
<!-- [CHAR_LIMIT=NONE] Battery app usage section header for past 24 hour -->
<string name="battery_app_usage_for_past_24">App usage for past 24 hr</string>
<!-- [CHAR_LIMIT=NONE] Battery system usage section header for past 24 hour -->
<string name="battery_system_usage_for_past_24">System usage for past 24 hr</string>
<!-- [CHAR_LIMIT=NONE] Battery system usage section header -->
<string name="battery_system_usage_for">System usage for</string>
<!-- [CHAR_LIMIT=NONE] Battery app usage section header -->
<string name="battery_app_usage_for">App usage for</string>
<!-- [CHAR_LIMIT=NONE] Battery usage section header for a specific time slot -->
<string name="battery_usage_time_am">am</string>
<!-- [CHAR_LIMIT=NONE] Battery usage section header for a specific time slot -->
<string name="battery_usage_time_pm">pm</string>
<!-- Process Stats strings -->
<skip />

View File

@@ -26,6 +26,12 @@
android:summary="@string/auto_rotate_summary_no_permission"
settings:controller="com.android.settings.display.SmartAutoRotatePermissionController" />
<com.android.settingslib.widget.BannerMessagePreference
android:key="camera_lock_state"
android:title="@string/auto_rotate_camera_lock_title"
android:summary="@string/auto_rotate_camera_lock_summary"
settings:controller="com.android.settings.display.SmartAutoRotateCameraStateController" />
<SwitchPreference
android:key="face_based_rotate"
android:title="@string/auto_rotate_switch_face_based"

View File

@@ -34,6 +34,7 @@
settings:allowDividerBelow="true" >
<Preference
android:key="behavior"
android:selectable="false"
android:summary="@string/important_conversation_behavior_summary"/>
<!-- Important conversations added here -->
<PreferenceCategory

View File

@@ -44,6 +44,5 @@
<SwitchPreference
android:key="wifi_tether_maximize_compatibility"
android:title="@string/wifi_hotspot_maximize_compatibility"
android:summary="@string/wifi_hotspot_maximize_compatibility_summary"/>
android:title="@string/wifi_hotspot_maximize_compatibility"/>
</PreferenceScreen>

View File

@@ -39,6 +39,7 @@ import android.util.Log;
import androidx.annotation.VisibleForTesting;
import com.android.settings.Settings.CreateShortcutActivity;
import com.android.settingslib.utils.ThreadUtils;
import java.util.ArrayList;
import java.util.List;
@@ -62,7 +63,7 @@ public class SettingsInitialize extends BroadcastReceiver {
final PackageManager pm = context.getPackageManager();
managedProfileSetup(context, pm, broadcast, userInfo);
webviewSettingSetup(context, pm, userInfo);
refreshExistingShortcuts(context);
ThreadUtils.postOnBackgroundThread(() -> refreshExistingShortcuts(context));
}
private void managedProfileSetup(Context context, final PackageManager pm, Intent broadcast,
@@ -142,5 +143,4 @@ public class SettingsInitialize extends BroadcastReceiver {
}
shortcutManager.updateShortcuts(updates);
}
}

View File

@@ -209,15 +209,15 @@ public class MagnificationSettingsFragment extends DashboardFragment {
mModeInfos.clear();
mModeInfos.add(new MagnificationModeInfo(getPrefContext().getText(
R.string.accessibility_magnification_mode_dialog_option_full_screen), null,
R.drawable.accessibility_magnification_full_screen, MagnificationMode.FULLSCREEN));
R.drawable.ic_illustration_fullscreen, MagnificationMode.FULLSCREEN));
mModeInfos.add(new MagnificationModeInfo(getPrefContext().getText(
R.string.accessibility_magnification_mode_dialog_option_window), null,
R.drawable.accessibility_magnification_window_screen, MagnificationMode.WINDOW));
R.drawable.ic_illustration_window, MagnificationMode.WINDOW));
mModeInfos.add(new MagnificationModeInfo(getPrefContext().getText(
R.string.accessibility_magnification_mode_dialog_option_switch),
getPrefContext().getText(
R.string.accessibility_magnification_area_settings_mode_switch_summary),
R.drawable.accessibility_magnification_switch, MagnificationMode.ALL));
R.drawable.ic_illustration_switch, MagnificationMode.ALL));
}
@VisibleForTesting

View File

@@ -19,29 +19,29 @@ package com.android.settings.applications.appinfo;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.hardware.usb.IUsbManager;
import android.os.ServiceManager;
import android.content.pm.verify.domain.DomainVerificationManager;
import android.content.pm.verify.domain.DomainVerificationUserState;
import android.os.UserHandle;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.applications.intentpicker.AppLaunchSettings;
import com.android.settings.applications.intentpicker.IntentPickerUtils;
import com.android.settingslib.R;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState;
public class AppOpenByDefaultPreferenceController extends AppInfoPreferenceControllerBase {
private IUsbManager mUsbManager;
private PackageManager mPackageManager;
private final DomainVerificationManager mDomainVerificationManager;
private String mPackageName;
public AppOpenByDefaultPreferenceController(Context context, String key) {
super(context, key);
mUsbManager = IUsbManager.Stub.asInterface(ServiceManager.getService(Context.USB_SERVICE));
mPackageManager = context.getPackageManager();
mDomainVerificationManager = context.getSystemService(DomainVerificationManager.class);
}
/** Set a package name for this controller. */
@@ -69,8 +69,7 @@ public class AppOpenByDefaultPreferenceController extends AppInfoPreferenceContr
&& !AppUtils.isBrowserApp(mContext, packageInfo.packageName,
UserHandle.myUserId())) {
preference.setVisible(true);
preference.setSummary(AppUtils.getLaunchByDefaultSummary(mParent.getAppEntry(),
mUsbManager, mPackageManager, mContext));
preference.setSummary(getSubtext());
} else {
preference.setVisible(false);
}
@@ -80,4 +79,18 @@ public class AppOpenByDefaultPreferenceController extends AppInfoPreferenceContr
protected Class<? extends SettingsPreferenceFragment> getDetailFragmentClass() {
return AppLaunchSettings.class;
}
@VisibleForTesting
CharSequence getSubtext() {
return mContext.getText(isLinkHandlingAllowed()
? R.string.app_link_open_always : R.string.app_link_open_never);
}
@VisibleForTesting
boolean isLinkHandlingAllowed() {
final DomainVerificationUserState userState =
IntentPickerUtils.getDomainVerificationUserState(mDomainVerificationManager,
mPackageName);
return userState == null ? false : userState.isLinkHandlingAllowed();
}
}

View File

@@ -364,7 +364,12 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
final TextView textView = linearLayout.findViewById(R.id.bt_battery_prediction);
if (estimateReady == 1) {
textView.setVisibility(View.VISIBLE);
textView.setText(StringUtil.formatElapsedTime(mContext, batteryEstimate, false));
textView.setText(
StringUtil.formatElapsedTime(
mContext,
batteryEstimate,
/* withSeconds */ false,
/* collapseTimeUnit */ false));
} else {
textView.setVisibility(View.GONE);
}

View File

@@ -318,7 +318,10 @@ public class DataUsageSummaryPreference extends Preference {
textResourceId = R.string.no_carrier_update_text;
}
updateTime = StringUtil.formatElapsedTime(
getContext(), updateAgeMillis, false /* withSeconds */);
getContext(),
updateAgeMillis,
false /* withSeconds */,
false /* collapseTimeUnit */);
}
carrierInfo.setText(TextUtils.expandTemplate(
getContext().getText(textResourceId),

View File

@@ -17,10 +17,10 @@
package com.android.settings.datetime.timezone.model;
import android.util.ArraySet;
import android.util.TimeUtils;
import com.android.i18n.timezone.CountryTimeZones;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -31,21 +31,6 @@ import java.util.Set;
*/
public class FilteredCountryTimeZones {
/**
* The timestamp used to determine which time zones to show to users by using the notUsedAfter
* metadata Android holds for each time zone.
*
* notUsedAfter exists because some time zones effectively "merge" with other time zones after
* a given point in time (i.e. they have identical transitions, offsets, etc.). After that
* point we only need to show one of the functionally identical ones.
*
* Rather than using System.currentTimeMillis(), UX folks asked for consistent behavior and so
* a timestamp known to be in the recent past is used. This should be updated occasionally but
* it doesn't have to be very often.
*/
private static final Instant MIN_USE_DATE_OF_TIMEZONE =
Instant.ofEpochMilli(1546300800000L); // 1/1/2019 00:00 UTC
private final CountryTimeZones mCountryTimeZones;
private final List<String> mPreferredTimeZoneIds;
private final Set<String> mAlternativeTimeZoneIds;
@@ -56,7 +41,7 @@ public class FilteredCountryTimeZones {
Set<String> alternativeTimeZoneIds = new ArraySet<>();
for (CountryTimeZones.TimeZoneMapping timeZoneMapping :
countryTimeZones.getTimeZoneMappings()) {
if (timeZoneMapping.isShownInPickerAt(MIN_USE_DATE_OF_TIMEZONE)) {
if (timeZoneMapping.isShownInPickerAt(TimeUtils.MIN_USE_DATE_OF_TIMEZONE)) {
String timeZoneId = timeZoneMapping.getTimeZoneId();
timeZoneIds.add(timeZoneId);
alternativeTimeZoneIds.addAll(timeZoneMapping.getAlternativeIds());

View File

@@ -60,14 +60,6 @@ public class BluetoothCodecDialogPreferenceController extends
((BaseBluetoothDialogPreference) mPreference).setCallback(this);
}
@Override
public void onHDAudioEnabled(boolean enabled) {
if (!enabled) {
// If option codec is disabled, SBC is the only only one available codec.
onIndexUpdated(convertCfgToBtnIndex(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC));
}
}
@Override
public List<Integer> getSelectableIndex() {
List<Integer> index = new ArrayList<>();

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.display;
import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static com.android.settings.display.SmartAutoRotateController.isRotationResolverServiceAvailable;
import android.content.Context;
import android.hardware.SensorPrivacyManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.widget.BannerMessagePreference;
/**
* The controller of camera based rotate privacy sensor warning preference. The preference appears
* when the privacy sensor service disables camera functionality completely.
*/
public class SmartAutoRotateCameraStateController extends BasePreferenceController {
private final SensorPrivacyManager mPrivacyManager;
private Preference mPreference;
public SmartAutoRotateCameraStateController(Context context, String key) {
super(context, key);
mPrivacyManager = SensorPrivacyManager.getInstance(context);
mPrivacyManager.addSensorPrivacyListener(CAMERA, enabled -> {
mPreference.setVisible(enabled);
updateState(mPreference);
});
}
@VisibleForTesting
boolean isCameraLocked() {
return mPrivacyManager.isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
((BannerMessagePreference) mPreference)
.setPositiveButtonText(R.string.allow)
.setPositiveButtonOnClickListener(v -> {
mPrivacyManager.setSensorPrivacy(CAMERA, false);
});
}
@Override
@AvailabilityStatus
public int getAvailabilityStatus() {
return isRotationResolverServiceAvailable(mContext)
&& isCameraLocked() ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE;
}
}

View File

@@ -15,6 +15,7 @@
*/
package com.android.settings.display;
import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
import static android.provider.Settings.Secure.CAMERA_AUTOROTATE;
import android.Manifest;
@@ -23,12 +24,15 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.hardware.SensorPrivacyManager;
import android.provider.Settings;
import android.service.rotationresolver.RotationResolverService;
import android.text.TextUtils;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.view.RotationPolicy;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.overlay.FeatureFactory;
@@ -41,10 +45,14 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
Preference.OnPreferenceChangeListener {
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final SensorPrivacyManager mPrivacyManager;
private Preference mPreference;
public SmartAutoRotateController(Context context, String preferenceKey) {
super(context, preferenceKey);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
mPrivacyManager = SensorPrivacyManager.getInstance(context);
mPrivacyManager.addSensorPrivacyListener(CAMERA, enabled -> updateState(mPreference));
}
@Override
@@ -53,16 +61,39 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
return UNSUPPORTED_ON_DEVICE;
}
return !RotationPolicy.isRotationLocked(mContext) && hasSufficientPermission(mContext)
? AVAILABLE : DISABLED_DEPENDENT_SETTING;
&& !isCameraLocked() ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
if (preference != null) {
preference.setEnabled(getAvailabilityStatus() == AVAILABLE);
}
}
/**
* Need this because all controller tests use RoboElectric. No easy way to mock this service,
* so we mock the call we need
*/
@VisibleForTesting
boolean isCameraLocked() {
return mPrivacyManager.isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA);
}
@Override
public boolean isChecked() {
return hasSufficientPermission(mContext) && Settings.Secure.getInt(
return hasSufficientPermission(mContext) && !isCameraLocked() && Settings.Secure.getInt(
mContext.getContentResolver(),
CAMERA_AUTOROTATE, 0) == 1;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
}
@Override
public boolean setChecked(boolean isChecked) {
mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_CAMERA_ROTATE_TOGGLE,

View File

@@ -19,6 +19,7 @@ import static com.android.settings.display.SmartAutoRotateController.hasSufficie
import static com.android.settings.display.SmartAutoRotateController.isRotationResolverServiceAvailable;
import android.app.settings.SettingsEnums;
import android.hardware.SensorPrivacyManager;
import android.os.Bundle;
import android.text.Html;
import android.view.LayoutInflater;
@@ -47,6 +48,7 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
private static final String TAG = "SmartAutoRotatePreferenceFragment";
private RotationPolicy.RotationPolicyListener mRotationPolicyListener;
private SensorPrivacyManager mPrivacyManager;
private AutoRotateSwitchBarController mSwitchBarController;
private static final String FACE_SWITCH_PREFERENCE_ID = "face_based_rotate";
@@ -66,6 +68,7 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
switchBar.show();
mSwitchBarController = new AutoRotateSwitchBarController(activity, switchBar,
getSettingsLifecycle());
mPrivacyManager = SensorPrivacyManager.getInstance(activity);
final Preference footerPreference = findPreference(FooterPreference.KEY_FOOTER);
if (footerPreference != null) {
footerPreference.setTitle(Html.fromHtml(getString(R.string.smart_rotate_text_headline),
@@ -84,9 +87,11 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
public void onChange() {
mSwitchBarController.onChange();
final boolean isLocked = RotationPolicy.isRotationLocked(getContext());
final boolean isCameraLocked = mPrivacyManager.isSensorPrivacyEnabled(
SensorPrivacyManager.Sensors.CAMERA);
final Preference preference = findPreference(FACE_SWITCH_PREFERENCE_ID);
if (preference != null && hasSufficientPermission(getContext())) {
preference.setEnabled(!isLocked);
preference.setEnabled(!isLocked && !isCameraLocked);
}
}
};

View File

@@ -229,10 +229,18 @@ public class AdvancedPowerUsageDetail extends DashboardFragment implements
final long backgroundTimeMs = bundle.getLong(EXTRA_BACKGROUND_TIME);
mForegroundPreference.setSummary(
TextUtils.expandTemplate(getText(R.string.battery_used_for),
StringUtil.formatElapsedTime(context, foregroundTimeMs, false)));
StringUtil.formatElapsedTime(
context,
foregroundTimeMs,
/* withSeconds */ false,
/* collapseTimeUnit */ false)));
mBackgroundPreference.setSummary(
TextUtils.expandTemplate(getText(R.string.battery_active_for),
StringUtil.formatElapsedTime(context, backgroundTimeMs, false)));
StringUtil.formatElapsedTime(
context,
backgroundTimeMs,
/* withSeconds */ false,
/* collapseTimeUnit */ false)));
}
@Override

View File

@@ -380,7 +380,7 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
final long usageTimeMs = entry.getTimeInForegroundMs();
if (shouldShowSummary(entry) && usageTimeMs >= DateUtils.MINUTE_IN_MILLIS) {
final CharSequence timeSequence =
StringUtil.formatElapsedTime(mContext, usageTimeMs, false);
StringUtil.formatElapsedTime(mContext, usageTimeMs, false, false);
preference.setSummary(
entry.isHidden()
? timeSequence

View File

@@ -0,0 +1,269 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.settings.fuelgauge;
import static java.lang.Math.round;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import androidx.appcompat.widget.AppCompatImageView;
import com.android.settings.R;
import com.android.settingslib.Utils;
import java.util.Locale;
/** A widget component to draw chart graph. */
public class BatteryChartView extends AppCompatImageView implements View.OnClickListener {
private static final String TAG = "BatteryChartView";
private static final int DEFAULT_TRAPEZOID_COUNT = 12;
/** Selects all trapezoid shapes. */
public static final int SELECTED_INDEX_ALL = -1;
public static final int SELECTED_INDEX_INVALID = -2;
/** A callback listener for selected group index is updated. */
public interface OnSelectListener {
void onSelect(int trapezoidIndex);
}
private int mDividerWidth;
private int mDividerHeight;
private int mTrapezoidCount;
private int mSelectedIndex;
private float mTrapezoidVOffset;
private float mTrapezoidHOffset;
// Colors for drawing the trapezoid shape and dividers.
private int mTrapezoidColor;
private int mTrapezoidSolidColor;
private final int mDividerColor = Color.parseColor("#CDCCC5");
private int[] mLevels;
private Paint mDividerPaint;
private Paint mTrapezoidPaint;
private TrapezoidSlot[] mTrapezoidSlot;
// Records the location to calculate selected index.
private MotionEvent mTouchUpEvent;
private BatteryChartView.OnSelectListener mOnSelectListener;
public BatteryChartView(Context context) {
super(context, null);
}
public BatteryChartView(Context context, AttributeSet attrs) {
super(context, attrs);
initializeColors(context);
setOnClickListener(this);
setSelectedIndex(SELECTED_INDEX_ALL);
setTrapezoidCount(DEFAULT_TRAPEZOID_COUNT);
}
/** Sets the total trapezoid count for drawing. */
public void setTrapezoidCount(int trapezoidCount) {
Log.i(TAG, "trapezoidCount:" + trapezoidCount);
mTrapezoidCount = trapezoidCount;
mTrapezoidSlot = new TrapezoidSlot[trapezoidCount];
// Allocates the trapezoid slot array.
for (int index = 0; index < trapezoidCount; index++) {
mTrapezoidSlot[index] = new TrapezoidSlot();
}
invalidate();
}
/** Sets all levels value to draw the trapezoid shape */
public void setLevels(int[] levels) {
// We should provide trapezoid count + 1 data to draw all trapezoids.
mLevels = levels.length == mTrapezoidCount + 1 ? levels : null;
setClickable(mLevels != null);
invalidate();
}
/** Sets the selected group index to draw highlight effect. */
public void setSelectedIndex(int index) {
if (mSelectedIndex != index) {
mSelectedIndex = index;
invalidate();
// Callbacks to the listener if we have.
if (mOnSelectListener != null) {
mOnSelectListener.onSelect(mSelectedIndex);
}
}
}
/** Sets the callback to monitor the selected group index. */
public void setOnSelectListener(BatteryChartView.OnSelectListener listener) {
mOnSelectListener = listener;
}
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
drawHorizontalDividers(canvas);
drawVerticalDividers(canvas);
drawTrapezoids(canvas);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// Caches the location to calculate selected trapezoid index.
final int action = event.getAction();
if (action == MotionEvent.ACTION_UP) {
mTouchUpEvent = MotionEvent.obtain(event);
} else if (action == MotionEvent.ACTION_CANCEL) {
mTouchUpEvent = null; // reset
}
return super.onTouchEvent(event);
}
@Override
public void onClick(View view) {
if (mTouchUpEvent == null) {
Log.w(TAG, "invalid motion event for onClick() callback");
return;
}
final int trapezoidIndex = getTrapezoidIndex(mTouchUpEvent.getX());
// Selects all if users click the same trapezoid item two times.
if (trapezoidIndex == mSelectedIndex) {
setSelectedIndex(SELECTED_INDEX_ALL);
} else {
setSelectedIndex(trapezoidIndex);
}
view.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
}
private void initializeColors(Context context) {
setBackgroundColor(Color.TRANSPARENT);
mTrapezoidSolidColor = Utils.getColorAccentDefaultColor(context);
mTrapezoidColor = Utils.getDisabled(context, mTrapezoidSolidColor);
// Initializes the divider line paint.
final Resources resources = getContext().getResources();
mDividerWidth = resources.getDimensionPixelSize(R.dimen.chartview_divider_width);
mDividerHeight = resources.getDimensionPixelSize(R.dimen.chartview_divider_height);
mDividerPaint = new Paint();
mDividerPaint.setAntiAlias(true);
mDividerPaint.setColor(mDividerColor);
mDividerPaint.setStyle(Paint.Style.STROKE);
mDividerPaint.setStrokeWidth(mDividerWidth);
Log.i(TAG, "mDividerWidth:" + mDividerWidth);
Log.i(TAG, "mDividerHeight:" + mDividerHeight);
// Initializes the trapezoid paint.
mTrapezoidHOffset = resources.getDimension(R.dimen.chartview_trapezoid_margin_start);
mTrapezoidVOffset = resources.getDimension(R.dimen.chartview_trapezoid_margin_bottom);
mTrapezoidPaint = new Paint();
mTrapezoidPaint.setAntiAlias(true);
mTrapezoidPaint.setColor(mTrapezoidSolidColor);
mTrapezoidPaint.setStyle(Paint.Style.FILL);
mTrapezoidPaint.setPathEffect(
new CornerPathEffect(
resources.getDimensionPixelSize(R.dimen.chartview_trapezoid_radius)));
}
private void drawHorizontalDividers(Canvas canvas) {
// Draws the top divider line for 100% curve.
float offsetY = mDividerWidth * 0.5f;
canvas.drawLine(0, offsetY, getWidth(), offsetY, mDividerPaint);
// Draws the center divider line for 50% curve.
final float availableSpace =
getHeight() - mDividerWidth * 2 - mTrapezoidVOffset - mDividerHeight;
offsetY = mDividerWidth + availableSpace * 0.5f;
canvas.drawLine(0, offsetY, getWidth(), offsetY, mDividerPaint);
// Draws the center divider line for 0% curve.
offsetY = getHeight() - mDividerHeight - mDividerWidth * 0.5f;
canvas.drawLine(0, offsetY, getWidth(), offsetY, mDividerPaint);
}
private void drawVerticalDividers(Canvas canvas) {
final int dividerCount = mTrapezoidCount + 1;
final float dividerSpace = dividerCount * mDividerWidth;
final float unitWidth = (getWidth() - dividerSpace) / (float) mTrapezoidCount;
final float startY = getHeight() - mDividerHeight;
final float trapezoidSlotOffset = mTrapezoidHOffset + mDividerWidth * 0.5f;
// Draws each vertical dividers.
float startX = mDividerWidth * 0.5f;
for (int index = 0; index < dividerCount; index++) {
canvas.drawLine(startX, startY, startX, getHeight(), mDividerPaint);
final float nextX = startX + mDividerWidth + unitWidth;
// Updates the trapezoid slots for drawing.
if (index < mTrapezoidSlot.length) {
mTrapezoidSlot[index].mLeft = round(startX + trapezoidSlotOffset);
mTrapezoidSlot[index].mRight = round(nextX - trapezoidSlotOffset);
}
startX = nextX;
}
}
private void drawTrapezoids(Canvas canvas) {
// Ignores invalid trapezoid data.
if (mLevels == null) {
return;
}
final float trapezoidBottom =
getHeight() - mDividerHeight - mDividerWidth - mTrapezoidVOffset;
final float availableSpace = trapezoidBottom - mDividerWidth;
final float unitHeight = availableSpace / 100f;
// Draws all trapezoid shapes into the canvas.
final Path trapezoidPath = new Path();
for (int index = 0; index < mTrapezoidCount; index++) {
// Configures the trapezoid paint color.
mTrapezoidPaint.setColor(
mSelectedIndex == index || mSelectedIndex == SELECTED_INDEX_ALL
? mTrapezoidSolidColor
: mTrapezoidColor);
final float leftTop = round(trapezoidBottom - mLevels[index] * unitHeight);
final float rightTop = round(trapezoidBottom - mLevels[index + 1] * unitHeight);
trapezoidPath.reset();
trapezoidPath.moveTo(mTrapezoidSlot[index].mLeft, trapezoidBottom);
trapezoidPath.lineTo(mTrapezoidSlot[index].mLeft, leftTop);
trapezoidPath.lineTo(mTrapezoidSlot[index].mRight, rightTop);
trapezoidPath.lineTo(mTrapezoidSlot[index].mRight, trapezoidBottom);
// A tricky way to make the trapezoid shape drawing the rounded corner.
trapezoidPath.lineTo(mTrapezoidSlot[index].mLeft, trapezoidBottom);
trapezoidPath.lineTo(mTrapezoidSlot[index].mLeft, leftTop);
// Draws the trapezoid shape into canvas.
canvas.drawPath(trapezoidPath, mTrapezoidPaint);
}
}
// Searches the corresponding trapezoid index from x location.
private int getTrapezoidIndex(float x) {
for (int index = 0; index < mTrapezoidSlot.length; index++) {
final TrapezoidSlot slot = mTrapezoidSlot[index];
if (x >= slot.mLeft && x <= slot.mRight) {
return index;
}
}
return SELECTED_INDEX_INVALID;
}
// A container class for each trapezoid left and right location.
private static final class TrapezoidSlot {
public float mLeft;
public float mRight;
@Override
public String toString() {
return String.format(Locale.US, "TrapezoidSlot[%f,%f]", mLeft, mRight);
}
}
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.settings.fuelgauge;
import android.content.ContentValues;
/** A container class to carry data from {@link ContentValues}. */
public final class BatteryHistEntry {
private static final String TAG = "BatteryHistEntry";
public final long mUid;
public final long mUserId;
public final String mAppLabel;
public final String mPackageName;
// Whether the data is represented as system component or not?
public final boolean mIsHidden;
// Records the timestamp relative information.
public final long mTimestamp;
public final String mZoneId;
// Records the battery usage relative information.
public final double mTotalPower;
public final double mConsumePower;
public final double mPercentOfTotal;
public final long mForegroundUsageTimeInMs;
public final long mBackgroundUsageTimeInMs;
public final int mDrainType;
public final int mConsumerType;
// Records the battery intent relative information.
public final int mBatteryLevel;
public final int mBatteryStatus;
public final int mBatteryHealth;
private boolean mIsValidEntry = true;
private ContentValues mContentValues;
public BatteryHistEntry(ContentValues contentValues) {
mContentValues = contentValues;
mUid = getLong("uid");
mUserId = getLong("userId");
mAppLabel = getString("appLabel");
mPackageName = getString("packageName");
mIsHidden = getBoolean("isHidden");
mTimestamp = getLong("timestamp");
mZoneId = getString("zoneId");
mTotalPower = getDouble("totalPower");
mConsumePower = getDouble("consumePower");
mPercentOfTotal = getDouble("percentOfTotal");
mForegroundUsageTimeInMs = getLong("foregroundUsageTimeInMs");
mBackgroundUsageTimeInMs = getLong("backgroundUsageTimeInMs");
mDrainType = getInteger("drainType");
mConsumerType = getInteger("consumerType");
mBatteryLevel = getInteger("batteryLevel");
mBatteryStatus = getInteger("batteryStatus");
mBatteryHealth = getInteger("batteryHealth");
}
/** Whether this {@link BatteryHistEntry} is valid or not? */
public boolean isValidEntry() {
return mIsValidEntry;
}
private int getInteger(String key) {
if (mContentValues != null && mContentValues.containsKey(key)) {
return mContentValues.getAsInteger(key);
};
mIsValidEntry = false;
return -1;
}
private long getLong(String key) {
if (mContentValues != null && mContentValues.containsKey(key)) {
return mContentValues.getAsLong(key);
}
mIsValidEntry = false;
return -1L;
}
private double getDouble(String key) {
if (mContentValues != null && mContentValues.containsKey(key)) {
return mContentValues.getAsDouble(key);
}
mIsValidEntry = false;
return 0f;
}
private String getString(String key) {
if (mContentValues != null && mContentValues.containsKey(key)) {
return mContentValues.getAsString(key);
}
mIsValidEntry = false;
return null;
}
private boolean getBoolean(String key) {
if (mContentValues != null && mContentValues.containsKey(key)) {
return mContentValues.getAsBoolean(key);
}
mIsValidEntry = false;
return false;
}
}

View File

@@ -19,8 +19,8 @@ package com.android.settings.fuelgauge;
import android.content.Context;
import android.os.BatteryUsageStats;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
@@ -28,26 +28,26 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.android.settings.widget.UsageView;
import com.android.settings.overlay.FeatureFactory;
/**
* Custom preference for displaying power consumption as a bar and an icon on the left for the
* subsystem/app type.
* Custom preference for displaying the battery level as chart graph.
*/
public class BatteryHistoryPreference extends Preference {
private static final String TAG = "BatteryHistoryPreference";
private CharSequence mSummary;
private TextView mSummaryView;
@VisibleForTesting
boolean hideSummary;
@VisibleForTesting
BatteryInfo mBatteryInfo;
public BatteryHistoryPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setLayoutResource(R.layout.battery_usage_graph);
final boolean isChartGraphEnabled =
FeatureFactory.getFactory(context).getPowerUsageFeatureProvider(context)
.isChartGraphEnabled(context);
Log.i(TAG, "isChartGraphEnabled: " + isChartGraphEnabled);
if (isChartGraphEnabled) {
setLayoutResource(R.layout.battery_chart_graph);
}
setSelectable(false);
}
@@ -58,22 +58,6 @@ public class BatteryHistoryPreference extends Preference {
}, batteryUsageStats, false);
}
public void setBottomSummary(CharSequence text) {
mSummary = text;
if (mSummaryView != null) {
mSummaryView.setVisibility(View.VISIBLE);
mSummaryView.setText(mSummary);
}
hideSummary = false;
}
public void hideBottomSummary() {
if (mSummaryView != null) {
mSummaryView.setVisibility(View.GONE);
}
hideSummary = true;
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
@@ -81,18 +65,6 @@ public class BatteryHistoryPreference extends Preference {
if (mBatteryInfo == null) {
return;
}
((TextView) view.findViewById(R.id.charge)).setText(mBatteryInfo.batteryPercentString);
mSummaryView = (TextView) view.findViewById(R.id.bottom_summary);
if (mSummary != null) {
mSummaryView.setText(mSummary);
}
if (hideSummary) {
mSummaryView.setVisibility(View.GONE);
}
UsageView usageView = (UsageView) view.findViewById(R.id.battery_usage);
usageView.findViewById(R.id.label_group).setAlpha(.7f);
mBatteryInfo.bindHistory(usageView);
BatteryUtils.logRuntime(TAG, "onBindViewHolder", startTime);
}
}

View File

@@ -263,8 +263,11 @@ public class BatteryInfo {
context.getString(chargingLimitedResId, info.batteryPercentString);
} else if (chargeTimeMs > 0 && status != BatteryManager.BATTERY_STATUS_FULL) {
info.remainingTimeUs = PowerUtil.convertMsToUs(chargeTimeMs);
CharSequence timeString = StringUtil.formatElapsedTime(context,
PowerUtil.convertUsToMs(info.remainingTimeUs), false /* withSeconds */);
final CharSequence timeString = StringUtil.formatElapsedTime(
context,
PowerUtil.convertUsToMs(info.remainingTimeUs),
false /* withSeconds */,
true /* collapseTimeUnit */);
int resId = R.string.power_charging_duration;
info.remainingLabel = context.getString(
R.string.power_remaining_charging_duration_only, timeString);
@@ -287,7 +290,7 @@ public class BatteryInfo {
context,
PowerUtil.convertUsToMs(drainTimeUs),
null /* percentageString */,
estimate.isBasedOnUsage() && !shortString
false /* basedOnUsage */
);
info.chargeLabel = PowerUtil.getBatteryRemainingStringFormatted(
context,

View File

@@ -0,0 +1,105 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.android.settings.fuelgauge;
import android.annotation.IntDef;
import android.content.ContentValues;
import android.os.BatteryConsumer;
import android.os.BatteryUsageStats;
import android.os.SystemBatteryConsumer;
import android.os.UidBatteryConsumer;
import android.os.UserBatteryConsumer;
import android.os.UserHandle;
import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.TimeZone;
/** A utility class to convert data into another types. */
public final class ConvertUtils {
private static final String TAG = "ConvertUtils";
/** Invalid system battery consumer drain type. */
public static final int INVALID_DRAIN_TYPE = -1;
@IntDef(prefix = {"CONSUMER_TYPE"}, value = {
CONSUMER_TYPE_UNKNOWN,
CONSUMER_TYPE_UID_BATTERY,
CONSUMER_TYPE_USER_BATTERY,
CONSUMER_TYPE_SYSTEM_BATTERY,
})
@Retention(RetentionPolicy.SOURCE)
public static @interface ConsumerType {}
public static final int CONSUMER_TYPE_UNKNOWN = 0;
public static final int CONSUMER_TYPE_UID_BATTERY = 1;
public static final int CONSUMER_TYPE_USER_BATTERY = 2;
public static final int CONSUMER_TYPE_SYSTEM_BATTERY = 3;
/** Gets consumer type from {@link BatteryConsumer}. */
@ConsumerType
public static int getConsumerType(BatteryConsumer consumer) {
if (consumer instanceof UidBatteryConsumer) {
return CONSUMER_TYPE_UID_BATTERY;
} else if (consumer instanceof UserBatteryConsumer) {
return CONSUMER_TYPE_USER_BATTERY;
} else if (consumer instanceof SystemBatteryConsumer) {
return CONSUMER_TYPE_SYSTEM_BATTERY;
} else {
return CONSUMER_TYPE_UNKNOWN;
}
}
/** Gets battery drain type for {@link SystemBatteryConsumer}. */
public static int getDrainType(BatteryConsumer consumer) {
if (consumer instanceof SystemBatteryConsumer) {
return ((SystemBatteryConsumer) consumer).getDrainType();
}
return INVALID_DRAIN_TYPE;
}
public static ContentValues convert(
BatteryEntry entry,
BatteryUsageStats batteryUsageStats,
int batteryLevel,
int batteryStatus,
int batteryHealth,
long timestamp) {
final ContentValues values = new ContentValues();
values.put("uid", Long.valueOf(entry.getUid()));
values.put("userId",
Long.valueOf(UserHandle.getUserId(entry.getUid())));
values.put("appLabel", entry.getLabel());
values.put("packageName", entry.getDefaultPackageName());
values.put("isHidden", Boolean.valueOf(entry.isHidden()));
values.put("timestamp", Long.valueOf(timestamp));
values.put("zoneId", TimeZone.getDefault().getID());
values.put("totalPower",
Double.valueOf(batteryUsageStats.getConsumedPower()));
values.put("consumePower", Double.valueOf(entry.getConsumedPower()));
values.put("percentOfTotal", Double.valueOf(entry.percent));
values.put("foregroundUsageTimeInMs",
Long.valueOf(entry.getTimeInForegroundMs()));
values.put("backgroundUsageTimeInMs",
Long.valueOf(entry.getTimeInBackgroundMs()));
values.put("drainType", getDrainType(entry.getBatteryConsumer()));
values.put("consumerType", getConsumerType(entry.getBatteryConsumer()));
values.put("batteryLevel", Integer.valueOf(batteryLevel));
values.put("batteryStatus", Integer.valueOf(batteryStatus));
values.put("batteryHealth", Integer.valueOf(batteryHealth));
return values;
}
private ConvertUtils() {}
}

View File

@@ -17,14 +17,9 @@ import static com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpd
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import androidx.annotation.VisibleForTesting;
@@ -44,16 +39,11 @@ public class PowerUsageAdvanced extends PowerUsageBase {
private static final String TAG = "AdvancedBatteryUsage";
private static final String KEY_BATTERY_GRAPH = "battery_graph";
private static final String KEY_APP_LIST = "app_list";
private static final String KEY_SHOW_ALL_APPS = "show_all_apps";
@VisibleForTesting
static final int MENU_TOGGLE_APPS = Menu.FIRST + 1;
@VisibleForTesting
BatteryHistoryPreference mHistPref;
private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
private BatteryAppListPreferenceController mBatteryAppListPreferenceController;
@VisibleForTesting
boolean mShowAllApps = false;
@Override
public void onCreate(Bundle icicle) {
@@ -63,10 +53,6 @@ public class PowerUsageAdvanced extends PowerUsageBase {
mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_GRAPH);
mPowerUsageFeatureProvider = FeatureFactory.getFactory(context)
.getPowerUsageFeatureProvider(context);
// init the summary so other preferences won't have unnecessary move
updateHistPrefSummary(context);
restoreSavedInstance(icicle);
}
@Override
@@ -92,42 +78,6 @@ public class PowerUsageAdvanced extends PowerUsageBase {
return R.xml.power_usage_advanced;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add(Menu.NONE, MENU_TOGGLE_APPS, Menu.NONE,
mShowAllApps ? R.string.hide_extra_apps : R.string.show_all_apps);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_TOGGLE_APPS:
mShowAllApps = !mShowAllApps;
item.setTitle(mShowAllApps ? R.string.hide_extra_apps : R.string.show_all_apps);
mMetricsFeatureProvider.action(getContext(),
SettingsEnums.ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE,
mShowAllApps);
restartBatteryStatsLoader(BatteryUpdateType.MANUAL);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@VisibleForTesting
void restoreSavedInstance(Bundle savedInstance) {
if (savedInstance != null) {
mShowAllApps = savedInstance.getBoolean(KEY_SHOW_ALL_APPS, false);
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(KEY_SHOW_ALL_APPS, mShowAllApps);
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
@@ -151,22 +101,7 @@ public class PowerUsageAdvanced extends PowerUsageBase {
return;
}
updatePreference(mHistPref);
updateHistPrefSummary(context);
mBatteryAppListPreferenceController.refreshAppListGroup(mBatteryUsageStats, mShowAllApps);
}
private void updateHistPrefSummary(Context context) {
Intent batteryIntent =
context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
final boolean plugged = batteryIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) != 0;
if (mPowerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(context) && !plugged) {
mHistPref.setBottomSummary(
mPowerUsageFeatureProvider.getAdvancedUsageScreenInfoString());
} else {
mHistPref.hideBottomSummary();
}
mBatteryAppListPreferenceController.refreshAppListGroup(mBatteryUsageStats, true);
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =

View File

@@ -124,4 +124,9 @@ public interface PowerUsageFeatureProvider {
* Checks whether smart battery feature is supported in this device
*/
boolean isSmartBatterySupported();
/**
* Checks whether we should enable chart graph design or not
*/
boolean isChartGraphEnabled(Context context);
}

View File

@@ -150,4 +150,9 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider
return mContext.getResources().getBoolean(
com.android.internal.R.bool.config_smart_battery_available);
}
@Override
public boolean isChartGraphEnabled(Context context) {
return false;
}
}

View File

@@ -149,10 +149,16 @@ public class BackupCallingPreferenceController extends TelephonyTogglePreference
private boolean hasBackupCallingFeature(int subscriptionId) {
PersistableBundle carrierConfig = getCarrierConfigForSubId(subscriptionId);
return (carrierConfig != null)
&& carrierConfig.getBoolean(
Boolean featureEnableStatus = null;
if (carrierConfig != null) {
featureEnableStatus = carrierConfig.getBoolean(
CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL, false);
}
// TODO: remove log after fixing b/182326102
Log.d(LOG_TAG, "config " + CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL
+ "=" + featureEnableStatus + " for subId=" + mSubId);
return (featureEnableStatus != null) && featureEnableStatus.booleanValue();
}
private ImsMmTelManager getImsMmTelManager(int subId) {
if (!SubscriptionManager.isUsableSubscriptionId(subId)) {

View File

@@ -214,6 +214,8 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
@Override
public void onResume() {
super.onResume();
// TODO: remove log after fixing b/182326102
Log.d(LOG_TAG, "onResume() subId=" + mSubId);
if (mActiveSubsciptionsListener == null) {
mActiveSubsciptionsListener = new ActiveSubsciptionsListener(
getContext().getMainLooper(), getContext(), mSubId) {

View File

@@ -55,6 +55,7 @@ public class AllConversationsPreferenceController extends ConversationListPrefer
Preference pref = new Preference(mContext);
pref.setOrder(1);
pref.setSummary(R.string.other_conversations_summary);
pref.setSelectable(false);
return pref;
}

View File

@@ -480,7 +480,7 @@ public class WifiDetailPreferenceController2 extends AbstractPreferenceControlle
return mContext.getString(R.string.wifi_time_remaining, StringUtil.formatElapsedTime(
mContext,
Duration.between(now, expiryTime).getSeconds() * 1000,
false /* withSeconds */));
false /* withSeconds */, false /* collapseTimeUnit */));
}
// For more than 2 days, show the expiry date

View File

@@ -24,6 +24,8 @@ import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.SwitchPreference;
import com.android.settings.R;
/**
* This controller helps to manage the state of maximize compatibility switch preference.
*/
@@ -53,6 +55,9 @@ public class WifiTetherMaximizeCompatibilityPreferenceController extends
}
mPreference.setEnabled(is5GhzBandSupported());
((SwitchPreference) mPreference).setChecked(mIsChecked);
mPreference.setSummary(mWifiManager.isBridgedApConcurrencySupported()
? R.string.wifi_hotspot_maximize_compatibility_dual_ap_summary
: R.string.wifi_hotspot_maximize_compatibility_single_ap_summary);
}
@Override

View File

@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -33,6 +34,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.verify.domain.DomainVerificationManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@@ -66,6 +68,8 @@ public class AppOpenByDefaultPreferenceControllerTest {
private Preference mPreference;
@Mock
private PackageManager mPackageManager;
@Mock
private DomainVerificationManager mDomainVerificationManager;
private Context mContext;
private AppOpenByDefaultPreferenceController mController;
@@ -78,6 +82,8 @@ public class AppOpenByDefaultPreferenceControllerTest {
mController.setParentFragment(mFragment);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mContext.getSystemService(DomainVerificationManager.class)).thenReturn(
mDomainVerificationManager);
}
@Test
@@ -194,10 +200,27 @@ public class AppOpenByDefaultPreferenceControllerTest {
final AppEntry appEntry = mock(AppEntry.class);
appEntry.info = new ApplicationInfo();
when(mFragment.getAppEntry()).thenReturn(appEntry);
doReturn(true).when(mController).isLinkHandlingAllowed();
mController.updateState(mPreference);
verify(mPreference).setVisible(true);
verify(mPreference).setSummary(any());
}
@Test
public void getSubtext_allowedLinkHandling_returnAllowedString() {
final String allowdedString = "Allow app to open supported links";
doReturn(true).when(mController).isLinkHandlingAllowed();
assertThat(mController.getSubtext()).isEqualTo(allowdedString);
}
@Test
public void getSubtext_notAllowedLinkHandling_returnNotAllowedString() {
final String notAllowdedString = "Dont allow app to open links";
doReturn(false).when(mController).isLinkHandlingAllowed();
assertThat(mController.getSubtext()).isEqualTo(notAllowdedString);
}
}

View File

@@ -473,9 +473,9 @@ public class AdvancedBluetoothDetailsHeaderControllerTest {
@Test
public void showBatteryPredictionIfNecessary_estimateReadyIsAvailable_showCorrectValue() {
final String leftBatteryPrediction =
StringUtil.formatElapsedTime(mContext, 12000000, false).toString();
StringUtil.formatElapsedTime(mContext, 12000000, false, false).toString();
final String rightBatteryPrediction =
StringUtil.formatElapsedTime(mContext, 1200000, false).toString();
StringUtil.formatElapsedTime(mContext, 1200000, false, false).toString();
mController.showBatteryPredictionIfNecessary(1, 12000000,
mLayoutPreference.findViewById(R.id.layout_left));

View File

@@ -0,0 +1,82 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.display;
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import com.android.settings.testutils.ResolveInfoBuilder;
import com.android.settings.testutils.shadow.ShadowSensorPrivacyManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowSensorPrivacyManager.class)
public class SmartAutoRotateCameraStateControllerTest {
private static final String PACKAGE_NAME = "package_name";
private SmartAutoRotateCameraStateController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
final Context context = Mockito.spy(RuntimeEnvironment.application);
final ContentResolver contentResolver = RuntimeEnvironment.application.getContentResolver();
when(context.getContentResolver()).thenReturn(contentResolver);
final PackageManager packageManager = Mockito.mock(PackageManager.class);
when(context.getPackageManager()).thenReturn(packageManager);
doReturn(PACKAGE_NAME).when(packageManager).getRotationResolverPackageName();
mController = new SmartAutoRotateCameraStateController(context, "smart_auto_rotate");
when(mController.isCameraLocked()).thenReturn(false);
final ResolveInfo resolveInfo = new ResolveInfoBuilder(PACKAGE_NAME).build();
resolveInfo.serviceInfo = new ServiceInfo();
when(packageManager.resolveService(any(), anyInt())).thenReturn(resolveInfo);
}
@Test
public void getAvailabilityStatus_returnUnsupportedOnDevice() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_cameraNotEnabled_returnAvailableUnSearchAble() {
when(mController.isCameraLocked()).thenReturn(true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
}
}

View File

@@ -39,6 +39,7 @@ import android.provider.Settings;
import androidx.preference.Preference;
import com.android.settings.testutils.ResolveInfoBuilder;
import com.android.settings.testutils.shadow.ShadowSensorPrivacyManager;
import org.junit.Before;
import org.junit.Test;
@@ -48,8 +49,10 @@ import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowSensorPrivacyManager.class)
public class SmartAutoRotateControllerTest {
private static final String PACKAGE_NAME = "package_name";
@@ -72,6 +75,7 @@ public class SmartAutoRotateControllerTest {
doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission(
Manifest.permission.CAMERA, PACKAGE_NAME);
mController = new SmartAutoRotateController(context, "test_key");
when(mController.isCameraLocked()).thenReturn(false);
doReturn(mController.getPreferenceKey()).when(mPreference).getKey();
final ResolveInfo resolveInfo = new ResolveInfoBuilder(PACKAGE_NAME).build();
@@ -105,6 +109,12 @@ public class SmartAutoRotateControllerTest {
assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
}
@Test
public void getAvailabilityStatus_cameraDisabled_returnDisableDependentSetting() {
when(mController.isCameraLocked()).thenReturn(true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
}
private void enableAutoRotation() {
Settings.System.putIntForUser(mContentResolver,
Settings.System.ACCELEROMETER_ROTATION, 1, UserHandle.USER_CURRENT);

View File

@@ -0,0 +1,110 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.fuelgauge;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import android.content.ContentValues;
import android.os.BatteryConsumer;
import android.os.BatteryManager;
import android.os.BatteryUsageStats;
import android.os.SystemBatteryConsumer;
import android.os.UserHandle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import java.util.TimeZone;
@RunWith(RobolectricTestRunner.class)
public final class BatteryHistEntryTest {
@Mock
private BatteryEntry mockBatteryEntry;
@Mock
private BatteryUsageStats mBatteryUsageStats;
@Mock
private SystemBatteryConsumer mockSystemBatteryConsumer;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testConstructor_returnsExpectedResult() {
final int expectedType = 3;
when(mockBatteryEntry.getUid()).thenReturn(1001);
when(mockBatteryEntry.getLabel()).thenReturn("Settings");
when(mockBatteryEntry.getDefaultPackageName())
.thenReturn("com.google.android.settings.battery");
when(mockBatteryEntry.isHidden()).thenReturn(true);
when(mBatteryUsageStats.getConsumedPower()).thenReturn(5.1);
when(mockBatteryEntry.getConsumedPower()).thenReturn(1.1);
mockBatteryEntry.percent = 0.3;
when(mockBatteryEntry.getTimeInForegroundMs()).thenReturn(1234L);
when(mockBatteryEntry.getTimeInBackgroundMs()).thenReturn(5689L);
when(mockBatteryEntry.getBatteryConsumer())
.thenReturn(mockSystemBatteryConsumer);
when(mockSystemBatteryConsumer.getDrainType()).thenReturn(expectedType);
final ContentValues values =
ConvertUtils.convert(
mockBatteryEntry,
mBatteryUsageStats,
/*batteryLevel=*/ 12,
/*batteryStatus=*/ BatteryManager.BATTERY_STATUS_FULL,
/*batteryHealth=*/ BatteryManager.BATTERY_HEALTH_COLD,
/*timestamp=*/ 10001L);
final BatteryHistEntry entry = new BatteryHistEntry(values);
assertThat(entry.isValidEntry()).isTrue();
assertThat(entry.mUid).isEqualTo(1001);
assertThat(entry.mUserId).isEqualTo(UserHandle.getUserId(1001));
assertThat(entry.mAppLabel).isEqualTo("Settings");
assertThat(entry.mPackageName)
.isEqualTo("com.google.android.settings.battery");
assertThat(entry.mIsHidden).isTrue();
assertThat(entry.mTimestamp).isEqualTo(10001L);
assertThat(entry.mZoneId).isEqualTo(TimeZone.getDefault().getID());
assertThat(entry.mTotalPower).isEqualTo(5.1);
assertThat(entry.mConsumePower).isEqualTo(1.1);
assertThat(entry.mPercentOfTotal).isEqualTo(mockBatteryEntry.percent);
assertThat(entry.mForegroundUsageTimeInMs).isEqualTo(1234L);
assertThat(entry.mBackgroundUsageTimeInMs).isEqualTo(5689L);
assertThat(entry.mDrainType).isEqualTo(expectedType);
assertThat(entry.mConsumerType)
.isEqualTo(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
assertThat(entry.mBatteryLevel).isEqualTo(12);
assertThat(entry.mBatteryStatus)
.isEqualTo(BatteryManager.BATTERY_STATUS_FULL);
assertThat(entry.mBatteryHealth)
.isEqualTo(BatteryManager.BATTERY_HEALTH_COLD);
}
@Test
public void testConstructor_invalidField_returnsInvalidEntry() {
final BatteryHistEntry entry = new BatteryHistEntry(new ContentValues());
assertThat(entry.isValidEntry()).isFalse();
}
}

View File

@@ -1,105 +0,0 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.fuelgauge;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.android.settings.widget.UsageView;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class BatteryHistoryPreferenceTest {
private static final String TEST_STRING = "test";
@Mock
private PreferenceViewHolder mViewHolder;
@Mock
private BatteryInfo mBatteryInfo;
@Mock
private TextView mTextView;
@Mock
private UsageView mUsageView;
@Mock
private View mLabelView;
private BatteryHistoryPreference mBatteryHistoryPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
final Context context = RuntimeEnvironment.application;
final View itemView =
LayoutInflater.from(context).inflate(R.layout.battery_usage_graph, null);
mBatteryHistoryPreference = new BatteryHistoryPreference(context, null);
mBatteryHistoryPreference.mBatteryInfo = mBatteryInfo;
mViewHolder = spy(PreferenceViewHolder.createInstanceForTests(itemView));
when(mViewHolder.findViewById(R.id.battery_usage)).thenReturn(mUsageView);
when(mViewHolder.findViewById(R.id.charge)).thenReturn(mTextView);
when(mUsageView.findViewById(anyInt())).thenReturn(mLabelView);
}
@Test
public void testOnBindViewHolder_updateBatteryUsage() {
mBatteryHistoryPreference.onBindViewHolder(mViewHolder);
verify(mViewHolder).findViewById(R.id.battery_usage);
verify(mTextView).setText(nullable(String.class));
verify(mBatteryInfo).bindHistory(mUsageView);
}
@Test
public void testSetBottomSummary_updatesBottomSummaryTextIfSet() {
mBatteryHistoryPreference.setBottomSummary(TEST_STRING);
mBatteryHistoryPreference.onBindViewHolder(mViewHolder);
TextView view = (TextView) mViewHolder.findViewById(R.id.bottom_summary);
assertThat(view.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(view.getText()).isEqualTo(TEST_STRING);
assertThat(mBatteryHistoryPreference.hideSummary).isFalse();
}
@Test
public void testSetBottomSummary_leavesBottomSummaryTextBlankIfNotSet() {
mBatteryHistoryPreference.hideBottomSummary();
mBatteryHistoryPreference.onBindViewHolder(mViewHolder);
TextView view = (TextView) mViewHolder.findViewById(R.id.bottom_summary);
assertThat(view.getVisibility()).isEqualTo(View.GONE);
assertThat(view.getText()).isEqualTo("");
assertThat(mBatteryHistoryPreference.hideSummary).isTrue();
}
}

View File

@@ -150,10 +150,9 @@ public class BatteryInfoTest {
mBatteryUsageStats, estimate, SystemClock.elapsedRealtime() * 1000,
true /* shortString */);
// We only add special mention for the long string
assertThat(info.remainingLabel.toString()).contains(ENHANCED_STRING_SUFFIX);
// Both long and short strings should not have extra text
assertThat(info.remainingLabel.toString()).doesNotContain(ENHANCED_STRING_SUFFIX);
assertThat(info.suggestionLabel).contains(BATTERY_RUN_OUT_PREFIX);
// shortened string should not have extra text
assertThat(info2.remainingLabel.toString()).doesNotContain(ENHANCED_STRING_SUFFIX);
assertThat(info2.suggestionLabel).contains(BATTERY_RUN_OUT_PREFIX);
}

View File

@@ -0,0 +1,145 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.fuelgauge;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import android.content.ContentValues;
import android.os.BatteryConsumer;
import android.os.BatteryManager;
import android.os.BatteryUsageStats;
import android.os.SystemBatteryConsumer;
import android.os.UidBatteryConsumer;
import android.os.UserBatteryConsumer;
import android.os.UserHandle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.TimeZone;
@RunWith(RobolectricTestRunner.class)
public final class ConvertUtilsTest {
@Mock
private BatteryUsageStats mBatteryUsageStats;
@Mock
private BatteryEntry mockBatteryEntry;
@Mock
private BatteryConsumer mockBatteryConsumer;
@Mock
private UidBatteryConsumer mockUidBatteryConsumer;
@Mock
private UserBatteryConsumer mockUserBatteryConsumer;
@Mock
private SystemBatteryConsumer mockSystemBatteryConsumer;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testConvert_returnsExpectedContentValues() {
final int expectedType = 3;
when(mockBatteryEntry.getUid()).thenReturn(1001);
when(mockBatteryEntry.getLabel()).thenReturn("Settings");
when(mockBatteryEntry.getDefaultPackageName())
.thenReturn("com.google.android.settings.battery");
when(mockBatteryEntry.isHidden()).thenReturn(true);
when(mBatteryUsageStats.getConsumedPower()).thenReturn(5.1);
when(mockBatteryEntry.getConsumedPower()).thenReturn(1.1);
mockBatteryEntry.percent = 0.3;
when(mockBatteryEntry.getTimeInForegroundMs()).thenReturn(1234L);
when(mockBatteryEntry.getTimeInBackgroundMs()).thenReturn(5689L);
when(mockBatteryEntry.getBatteryConsumer())
.thenReturn(mockSystemBatteryConsumer);
when(mockSystemBatteryConsumer.getDrainType()).thenReturn(expectedType);
final ContentValues values =
ConvertUtils.convert(
mockBatteryEntry,
mBatteryUsageStats,
/*batteryLevel=*/ 12,
/*batteryStatus=*/ BatteryManager.BATTERY_STATUS_FULL,
/*batteryHealth=*/ BatteryManager.BATTERY_HEALTH_COLD,
/*timestamp=*/ 10001L);
assertThat(values.getAsLong("uid")).isEqualTo(1001L);
assertThat(values.getAsLong("userId"))
.isEqualTo(UserHandle.getUserId(1001));
assertThat(values.getAsString("appLabel")).isEqualTo("Settings");
assertThat(values.getAsString("packageName"))
.isEqualTo("com.google.android.settings.battery");
assertThat(values.getAsBoolean("isHidden")).isTrue();
assertThat(values.getAsLong("timestamp")).isEqualTo(10001L);
assertThat(values.getAsString("zoneId"))
.isEqualTo(TimeZone.getDefault().getID());
assertThat(values.getAsDouble("totalPower")).isEqualTo(5.1);
assertThat(values.getAsDouble("consumePower")).isEqualTo(1.1);
assertThat(values.getAsDouble("percentOfTotal")).isEqualTo(0.3);
assertThat(values.getAsLong("foregroundUsageTimeInMs")).isEqualTo(1234L);
assertThat(values.getAsLong("backgroundUsageTimeInMs")).isEqualTo(5689L);
assertThat(values.getAsInteger("drainType")).isEqualTo(expectedType);
assertThat(values.getAsInteger("consumerType"))
.isEqualTo(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
assertThat(values.getAsInteger("batteryLevel")).isEqualTo(12);
assertThat(values.getAsInteger("batteryStatus"))
.isEqualTo(BatteryManager.BATTERY_STATUS_FULL);
assertThat(values.getAsInteger("batteryHealth"))
.isEqualTo(BatteryManager.BATTERY_HEALTH_COLD);
}
@Test
public void testGetDrainType_returnsExpetcedResult() {
final int expectedType = 3;
when(mockSystemBatteryConsumer.getDrainType())
.thenReturn(expectedType);
assertThat(ConvertUtils.getDrainType(mockSystemBatteryConsumer))
.isEqualTo(expectedType);
}
@Test
public void testGetDrainType_notValidConsumer_returnsInvalidTypeValue() {
assertThat(ConvertUtils.getDrainType(mockUserBatteryConsumer))
.isEqualTo(ConvertUtils.INVALID_DRAIN_TYPE);
}
@Test
public void testGetConsumerType_returnsExpetcedResult() {
assertThat(ConvertUtils.getConsumerType(mockUidBatteryConsumer))
.isEqualTo(ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
assertThat(ConvertUtils.getConsumerType(mockUserBatteryConsumer))
.isEqualTo(ConvertUtils.CONSUMER_TYPE_USER_BATTERY);
assertThat(ConvertUtils.getConsumerType(mockSystemBatteryConsumer))
.isEqualTo(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
}
@Test
public void testGetConsumeType_invalidConsumer_returnsInvalidType() {
assertThat(ConvertUtils.getConsumerType(mockBatteryConsumer))
.isEqualTo(ConvertUtils.CONSUMER_TYPE_UNKNOWN);
}
}

View File

@@ -1,118 +0,0 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.fuelgauge;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import androidx.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class PowerUsageAdvancedTest {
@Mock
private PreferenceScreen mPreferenceScreen;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Menu mMenu;
@Mock
private MenuInflater mMenuInflater;
@Mock
private MenuItem mToggleAppsMenu;
private Context mContext;
private PowerUsageAdvanced mFragment;
private FakeFeatureFactory mFeatureFactory;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mFeatureFactory = FakeFeatureFactory.setupForTest();
when(mToggleAppsMenu.getItemId()).thenReturn(PowerUsageAdvanced.MENU_TOGGLE_APPS);
BatteryAppListPreferenceController.sConfig =
new BatteryAppListPreferenceController.Config() {
@Override
public boolean shouldShowBatteryAttributionList(Context context) {
return true;
}
};
mFragment = spy(new PowerUsageAdvanced());
mFragment.onAttach(mContext);
}
@Test
public void testSaveInstanceState_showAllAppsRestored() {
Bundle bundle = new Bundle();
mFragment.mShowAllApps = true;
doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
mFragment.onSaveInstanceState(bundle);
mFragment.restoreSavedInstance(bundle);
assertThat(mFragment.mShowAllApps).isTrue();
}
@Test
public void testOptionsMenu_menuAppToggle_metricEventInvoked() {
mFragment.mShowAllApps = false;
doNothing().when(mFragment).restartBatteryStatsLoader(anyInt());
mFragment.onOptionsItemSelected(mToggleAppsMenu);
verify(mFeatureFactory.metricsFeatureProvider).action(nullable(Context.class),
eq(MetricsProto.MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE), eq(true));
}
@Test
public void testOptionsMenu_toggleAppsEnabled() {
when(mFeatureFactory.powerUsageFeatureProvider.isPowerAccountingToggleEnabled())
.thenReturn(true);
mFragment.mShowAllApps = false;
mFragment.onCreateOptionsMenu(mMenu, mMenuInflater);
verify(mMenu).add(Menu.NONE, PowerUsageAdvanced.MENU_TOGGLE_APPS, Menu.NONE,
R.string.show_all_apps);
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.testutils.shadow;
import static org.mockito.Mockito.mock;
import android.content.Context;
import android.hardware.SensorPrivacyManager;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@Implements(value = SensorPrivacyManager.class)
public class ShadowSensorPrivacyManager {
@Implementation
public static SensorPrivacyManager getInstance(Context context) {
return mock(SensorPrivacyManager.class);
}
}

View File

@@ -579,7 +579,11 @@ public class WifiDetailPreferenceController2Test {
ZoneId.of("Europe/London"));
doShouldShowRemainingTimeTest(fakeNow, timeRemainingMs);
final String expectedSummary = mContext.getString(R.string.wifi_time_remaining,
StringUtil.formatElapsedTime(mContext, timeRemainingMs, false /* withSeconds */));
StringUtil.formatElapsedTime(
mContext,
timeRemainingMs,
false /* withSeconds */,
false /* collapseTimeUnit */));
final InOrder inOrder = inOrder(mMockHeaderController);
inOrder.verify(mMockHeaderController).setSecondSummary(expectedSummary);

View File

@@ -34,6 +34,8 @@ import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.testutils.ResourcesUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -52,29 +54,30 @@ public class WifiTetherMaximizeCompatibilityPreferenceControllerTest {
@Mock
private WifiTetherBasePreferenceController.OnTetherConfigUpdateListener mListener;
private Context mContext;
private WifiTetherMaximizeCompatibilityPreferenceController mController;
private SwitchPreference mPreference;
private SoftApConfiguration mConfig;
@Before
public void setUp() {
final Context context = spy(ApplicationProvider.getApplicationContext());
mContext = spy(ApplicationProvider.getApplicationContext());
mConfig = new SoftApConfiguration.Builder()
.setSsid("test_Ssid")
.setPassphrase(null, SoftApConfiguration.SECURITY_TYPE_OPEN)
.setBridgedModeOpportunisticShutdownEnabled(true)
.build();
doReturn(mWifiManager).when(context).getSystemService(Context.WIFI_SERVICE);
doReturn(mWifiManager).when(mContext).getSystemService(Context.WIFI_SERVICE);
doReturn(true).when(mWifiManager).isBridgedApConcurrencySupported();
doReturn(mConfig).when(mWifiManager).getSoftApConfiguration();
mController = new WifiTetherMaximizeCompatibilityPreferenceController(context, mListener);
mController = new WifiTetherMaximizeCompatibilityPreferenceController(mContext, mListener);
if (Looper.myLooper() == null) {
Looper.prepare();
}
final PreferenceManager preferenceManager = new PreferenceManager(context);
final PreferenceScreen screen = preferenceManager.createPreferenceScreen(context);
mPreference = new SwitchPreference(context);
final PreferenceManager preferenceManager = new PreferenceManager(mContext);
final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
mPreference = new SwitchPreference(mContext);
mPreference.setKey(WifiTetherMaximizeCompatibilityPreferenceController.PREF_KEY);
screen.addPreference(mPreference);
mController.displayPreference(screen);
@@ -104,6 +107,26 @@ public class WifiTetherMaximizeCompatibilityPreferenceControllerTest {
assertThat(mPreference.isEnabled()).isEqualTo(false);
}
@Test
public void updateDisplay_notSupportedBridgedApConcurrency_setSingleApSummary() {
doReturn(false).when(mWifiManager).isBridgedApConcurrencySupported();
mController.updateDisplay();
assertThat(mPreference.getSummary()).isEqualTo(ResourcesUtils.getResourcesString(mContext,
"wifi_hotspot_maximize_compatibility_single_ap_summary"));
}
@Test
public void updateDisplay_supportedBridgedApConcurrency_setDualApSummary() {
doReturn(true).when(mWifiManager).isBridgedApConcurrencySupported();
mController.updateDisplay();
assertThat(mPreference.getSummary()).isEqualTo(ResourcesUtils.getResourcesString(mContext,
"wifi_hotspot_maximize_compatibility_dual_ap_summary"));
}
@Test
public void updateDisplay_supported5GHzBandAndCountryCodeIsNotNull_setPreferenceEnabled() {
doReturn(true).when(mWifiManager).is5GHzBandSupported();