Snap for 5546586 from 416b49569a to qt-release

Change-Id: I765edf3aba0955f8db9027c936dbff61ebbcbf23
This commit is contained in:
android-build-team Robot
2019-05-09 03:10:36 +00:00
67 changed files with 1849 additions and 234 deletions

View File

@@ -1588,6 +1588,10 @@
android:exported="false"
android:screenOrientation="portrait"/>
<activity android:name=".biometrics.face.FaceEnrollEducation"
android:exported="false"
android:screenOrientation="portrait"/>
<activity android:name=".biometrics.face.FaceEnrollEnrolling"
android:exported="false"
android:screenOrientation="portrait"/>

View File

@@ -0,0 +1,42 @@
<!--
~ Copyright (C) 2019 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector android:height="24dp" android:width="24dp" android:viewportHeight="24"
android:viewportWidth="24"
android:tint="?android:attr/colorControlNormal">
<group android:name="_R_G">
<group android:name="_R_G_L_0_G">
<path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000"
android:fillAlpha="1" android:fillType="nonZero"
android:pathData=" M15 8 C15,6.58 14.5,5.27 13.67,4.24 C14.09,4.1 14.53,4 15,4 C17.21,4 19,5.79 19,8 C19,10.21 17.21,12 15,12 C14.57,12 14.16,11.91 13.77,11.79 C13.74,11.78 13.71,11.77 13.67,11.76 C14.5,10.73 15,9.42 15,8c M16.66 13.13 C18.03,14.06 19,15.32 19,17 C19,17 19,20 19,20 C19,20 23,20 23,20 C23,20 23,17 23,17 C23,14.82 19.42,13.53 16.66,13.13c M9 6 C7.9,6 7,6.9 7,8 C7,9.1 7.9,10 9,10 C10.1,10 11,9.1 11,8 C11,6.9 10.1,6 9,6c M9 15 C6.3,15 3.2,16.29 3,17.01 C3,17.01 3,18 3,18 C3,18 15,18 15,18 C15,18 15,17 15,17 C14.8,16.29 11.7,15 9,15c M9 4 C11.21,4 13,5.79 13,8 C13,10.21 11.21,12 9,12 C6.79,12 5,10.21 5,8 C5,5.79 6.79,4 9,4c M9 13 C11.67,13 17,14.34 17,17 C17,17 17,20 17,20 C17,20 1,20 1,20 C1,20 1,17 1,17 C1,14.34 6.33,13 9,13c "/>
</group>
</group>
<group android:name="time_group"/>
</vector>
</aapt:attr>
<target android:name="time_group">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="translateX" android:duration="2000"
android:startOffset="0" android:valueFrom="0" android:valueTo="1"
android:valueType="floatType"/>
</set>
</aapt:attr>
</target>
</animated-vector>

View File

@@ -0,0 +1,45 @@
<!--
~ Copyright (C) 2019 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector android:height="24dp" android:width="24dp" android:viewportHeight="24"
android:viewportWidth="24"
android:tint="?android:attr/colorControlNormal">
<group android:name="_R_G">
<group android:name="_R_G_L_0_G">
<path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000"
android:fillAlpha="1" android:fillType="nonZero"
android:pathData=" M12 2 C12,2 3.82,5.64 3.82,5.64 C3.82,5.64 3.82,11.09 3.82,11.09 C3.82,16.14 7.31,20.85 12,22 C16.69,20.85 20.18,16.14 20.18,11.09 C20.18,11.09 20.18,5.64 20.18,5.64 C20.18,5.64 12,2 12,2c M18.18 11.09 C18.18,12.64 17.77,14.14 17.08,15.47 C15.77,14.5 13.4,14 12,14 C10.6,14 8.23,14.5 6.92,15.47 C6.23,14.14 5.82,12.64 5.82,11.09 C5.82,11.09 5.82,6.94 5.82,6.94 C5.82,6.94 12,4.19 12,4.19 C12,4.19 18.18,6.94 18.18,6.94 C18.18,6.94 18.18,11.09 18.18,11.09c "/>
<path android:name="_R_G_L_0_G_D_1_P_0" android:fillColor="#000000"
android:fillAlpha="1" android:fillType="nonZero"
android:pathData=" M12 7.5 C13.66,7.5 15,8.84 15,10.5 C15,12.16 13.66,13.5 12,13.5 C10.34,13.5 9,12.16 9,10.5 C9,8.84 10.34,7.5 12,7.5c "/>
</group>
</group>
<group android:name="time_group"/>
</vector>
</aapt:attr>
<target android:name="time_group">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="translateX" android:duration="2000"
android:startOffset="0" android:valueFrom="0" android:valueTo="1"
android:valueType="floatType"/>
</set>
</aapt:attr>
</target>
</animated-vector>

View File

@@ -0,0 +1,45 @@
<!--
~ Copyright (C) 2019 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector android:height="24dp" android:width="24dp" android:viewportHeight="24"
android:viewportWidth="24"
android:tint="?android:attr/colorControlNormal">
<group android:name="_R_G">
<group android:name="_R_G_L_0_G">
<path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000000"
android:fillAlpha="1" android:fillType="nonZero"
android:pathData=" M12 7 C9.52,7 7.5,9.02 7.5,11.5 C7.5,13.98 9.52,16 12,16 C14.48,16 16.5,13.98 16.5,11.5 C16.5,9.02 14.48,7 12,7c M12 14.2 C10.51,14.2 9.3,12.99 9.3,11.5 C9.3,10.01 10.51,8.8 12,8.8 C13.49,8.8 14.7,10.01 14.7,11.5 C14.7,12.99 13.49,14.2 12,14.2c "/>
<path android:name="_R_G_L_0_G_D_1_P_0" android:fillColor="#000000"
android:fillAlpha="1" android:fillType="nonZero"
android:pathData=" M12 4 C7,4 2.73,7.11 1,11.5 C2.73,15.89 7,19 12,19 C17,19 21.27,15.89 23,11.5 C21.27,7.11 17,4 12,4c M12 17 C8.21,17 4.83,14.87 3.18,11.5 C4.83,8.13 8.21,6 12,6 C15.79,6 19.17,8.13 20.82,11.5 C19.17,14.87 15.79,17 12,17c "/>
</group>
</group>
<group android:name="time_group"/>
</vector>
</aapt:attr>
<target android:name="time_group">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator android:propertyName="translateX" android:duration="2000"
android:startOffset="0" android:valueFrom="0" android:valueTo="1"
android:valueType="floatType"/>
</set>
</aapt:attr>
</target>
</animated-vector>

View File

@@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2018 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
<com.google.android.setupdesign.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:FaceEnrollAccessibilitySwitch="http://schemas.android.com/apk/res/com.android.settings"
style="?attr/face_layout_theme"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
style="@style/SudContentFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical">
<com.google.android.setupdesign.view.RichTextView
android:id="@+id/sud_layout_description"
style="@style/SudDescription.Glif"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAlignment="center"
android:text="@string/security_settings_face_enroll_education_message"/>
<com.google.android.setupdesign.view.RichTextView
android:id="@+id/error_text"
style="@style/SudDescription.Glif"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="48dp">
<com.google.android.setupdesign.view.IllustrationVideoView
android:id="@+id/illustration_normal"
style="@style/SudContentIllustration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:sudVideo="@raw/face_education"/>
<ImageView
android:id="@+id/illustration_accessibility"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="invisible"
android:background="@drawable/face_enroll_introduction"/>
</FrameLayout>
<!-- Contains the buttons and extra information text at the bottom -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center_horizontal|bottom">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/accessibility_button"
style="@style/SudGlifButton.Secondary"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/security_settings_face_enroll_introduction_accessibility"/>
<com.android.settings.biometrics.face.FaceEnrollAccessibilityToggle
android:id="@+id/toggle_diversity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
FaceEnrollAccessibilitySwitch:messageText="@string/security_settings_face_enroll_introduction_accessibility_diversity"/>
</FrameLayout>
</LinearLayout>
</LinearLayout>
</com.google.android.setupdesign.GlifLayout>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2018 The Android Open Source Project
~ Copyright (C) 2019 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -37,13 +37,13 @@
style="@style/SudDescription.Glif"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/security_settings_face_enroll_introduction_message" />
android:text="@string/security_settings_face_enroll_introduction_message"/>
<com.google.android.setupdesign.view.RichTextView
android:id="@+id/error_text"
style="@style/SudDescription.Glif"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"/>
<FrameLayout
android:layout_width="match_parent"
@@ -52,18 +52,10 @@
<com.google.android.setupdesign.view.IllustrationVideoView
android:id="@+id/illustration_normal"
style="@style/SudContentIllustration"
android:layout_width="240dp"
android:layout_height="240dp"
app:sudVideo="@raw/face_enroll_introduction_animation" />
<ImageView
android:id="@+id/illustration_accessibility"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="invisible"
android:background="@drawable/face_enroll_introduction" />
style="@style/SudContentIllustration"
app:sudVideo="@raw/face_enroll_introduction_animation"/>
</FrameLayout>
@@ -74,29 +66,7 @@
android:orientation="vertical"
android:layout_gravity="center_horizontal|bottom">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/accessibility_button"
style="@style/SudGlifButton.Secondary"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/security_settings_face_enroll_introduction_accessibility" />
<com.android.settings.biometrics.face.FaceEnrollAccessibilityToggle
android:id="@+id/toggle_diversity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
FaceEnrollAccessibilitySwitch:messageText="@string/security_settings_face_enroll_introduction_accessibility_diversity"/>
</FrameLayout>
<LinearLayout
android:id="@+id/footer_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
@@ -107,15 +77,61 @@
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_face_enroll_introduction_detail">
android:background="@drawable/ic_face_enroll_introduction_shield">
</ImageView>
<Space
android:layout_width="8dp"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/security_settings_face_enroll_introduction_footer_message"/>
android:text="@string/security_settings_face_enroll_introduction_footer_part_1"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:paddingTop="24dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_face_enroll_introduction_visibility">
</ImageView>
<Space
android:layout_width="8dp"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/security_settings_face_enroll_introduction_footer_part_2"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:paddingTop="24dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_face_enroll_introduction_people">
</ImageView>
<Space
android:layout_width="8dp"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/security_settings_face_enroll_introduction_footer_part_3"/>
</LinearLayout>
</LinearLayout>

View File

@@ -18,6 +18,8 @@
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/settings_homepage_container"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
@@ -57,7 +59,7 @@
<Space
android:layout_width="match_parent"
android:layout_height="@*android:dimen/status_bar_height"
android:layout_height="0dp"
android:background="@android:color/transparent"
app:layout_scrollFlags="scroll|enterAlways"/>

View File

View File

View File

@@ -15,19 +15,17 @@
-->
<resources>
<color name="switchbar_switch_track_tint">#82000000</color>
<color name="switchbar_switch_thumb_tint">@android:color/black</color>
<color name="homepage_accessibility_background">#783BE5</color>
<color name="homepage_support_background">#3F5FBD</color>
<!-- 80% black for status bar of homepage -->
<color name="homepage_status_bar_color">#cc000000</color>
<color name="homepage_card_dismissal_background">@*android:color/material_grey_900</color>
<color name="contextual_card_background">@*android:color/material_grey_900</color>
<color name="search_bar_background">@*android:color/material_grey_800</color>
<!-- Dialog background color -->
<color name="dialog_background">@*android:color/material_grey_800</color>
<color name="notification_importance_selection_bg">@*android:color/material_grey_800</color>
<color name="notification_importance_button_selected">#AECBFA</color> <!-- material blue 200 -->
<color name="notification_importance_button_unselected">#5F6368</color>
<color name="switchbar_switch_track_tint">#82000000</color>
<color name="switchbar_switch_thumb_tint">@android:color/black</color>
<color name="homepage_accessibility_background">#783BE5</color>
<color name="homepage_support_background">#3F5FBD</color>
<color name="homepage_card_dismissal_background">@*android:color/material_grey_900</color>
<color name="contextual_card_background">@*android:color/material_grey_900</color>
<color name="search_bar_background">@*android:color/material_grey_800</color>
<!-- Dialog background color -->
<color name="dialog_background">@*android:color/material_grey_800</color>
<color name="notification_importance_selection_bg">@*android:color/material_grey_800</color>
<color name="notification_importance_button_selected">#AECBFA</color> <!-- material blue 200 -->
<color name="notification_importance_button_unselected">#5F6368</color>
</resources>

View File

@@ -23,7 +23,9 @@
<color name="divider_color">#20ffffff</color>
<color name="title_color">@android:color/holo_blue_light</color>
<color name="setup_lock_pattern_view_regular_color_light">@color/lock_pattern_view_regular_color</color>
<color name="setup_lock_pattern_view_regular_color_light">
@color/lock_pattern_view_regular_color
</color>
<color name="setup_lock_pattern_view_success_color_dark">#ff84ffff</color>
<color name="setup_lock_pattern_view_success_color_light">@color/sud_color_accent_light</color>
<color name="setup_lock_pattern_view_error_color_dark">#fff44336</color>
@@ -133,9 +135,6 @@
<!-- launcher icon color -->
<color name="icon_launcher_setting_color">@*android:color/accent_device_default_light</color>
<!-- 80% white for status bar of homepage -->
<color name="homepage_status_bar_color">#ccFFFFFF</color>
<!-- QR code scanner colors -->
<color name="qr_corner_line_color">#ffdadce0</color>
<color name="qr_focused_corner_line_color">#ff1a73e8</color>

View File

@@ -409,5 +409,5 @@
<dimen name="two_target_min_width">80dp</dimen>
<!-- Maximum height for SliceView, override on slices/view/src/main/res/values/dimens.xml -->
<dimen name="abc_slice_large_height">360dp</dimen>
<dimen name="abc_slice_large_height">480dp</dimen>
</resources>

View File

@@ -888,6 +888,12 @@
<string name="security_settings_face_preference_summary_none">Tap to set up face authentication</string>
<!-- Title shown for menu item that launches face settings or enrollment. [CHAR LIMIT=32] -->
<string name="security_settings_face_preference_title">Face authentication</string>
<!-- Introduction title shown in face enrollment education screen [CHAR LIMIT=40] -->
<string name="security_settings_face_enroll_education_title">How to set up Face unlock</string>
<!-- Introduction title shown in face enrollment education screen to show the face authentication feature, when face unlock is disabled by device admin [CHAR LIMIT=40] -->
<string name="security_settings_face_enroll_education_title_unlock_disabled">Use your face to authenticate</string>
<!-- Introduction detail message shown in face education [CHAR LIMIT=NONE] -->
<string name="security_settings_face_enroll_education_message"></string>
<!-- Button shown which shows accessibility toggles for face enrollment when clicked. [CHAR LIMIT=32] -->
<string name="security_settings_face_enroll_introduction_accessibility">Use accessibility setup</string>
<!-- Additional details shown when the accessibility toggle is expanded. [CHAR LIMIT=NONE]-->
@@ -908,8 +914,12 @@
<string name="security_settings_face_enroll_introduction_message_unlock_disabled">Use your face to unlock your phone or approve purchases.\n\nNote: You can\u2019t use your face to unlock this device. For more information, contact your organization\u2019s admin.</string>
<!-- Introduction detail message shown in face enrollment screen in setup wizard. [CHAR LIMIT=NONE] -->
<string name="security_settings_face_enroll_introduction_message_setup">Use your face to unlock your phone, authorize purchases, or sign in to apps</string>
<!-- Introduction detail message shown in face enrollment that provides extra detais. [CHAR LIMIT=NONE] -->
<string name="security_settings_face_enroll_introduction_footer_message"></string>
<!-- Introduction message shown in face enrollment that provides extra detail. [CHAR LIMIT=NONE] -->
<string name="security_settings_face_enroll_introduction_footer_part_1"></string>
<!-- Introduction message shown in face enrollment that provides extra detail. [CHAR LIMIT=NONE] -->
<string name="security_settings_face_enroll_introduction_footer_part_2"></string>
<!-- Introduction message shown in face enrollment that provides extra detail. [CHAR LIMIT=NONE] -->
<string name="security_settings_face_enroll_introduction_footer_part_3"></string>
<!-- Title shown in face enrollment dialog [CHAR LIMIT=40] -->
<string name="security_settings_face_enroll_repeat_title">Center your face in the circle</string>
<!-- Button text to skip enrollment of face [CHAR LIMIT=40] -->
@@ -2895,7 +2905,7 @@
<string name="wallpaper_settings_fragment_title">Choose wallpaper from</string>
<!-- Styles and Wallpaper settings title [CHAR_LIMIT=46] -->
<string name="style_suggestion_title">Customize your Pixel</string>
<!-- Styles and Wallpapers summary [CHAR_LIMIT=55] -->
<!-- Styles and Wallpapers summary [CHAR_LIMIT=70] -->
<string name="style_suggestion_summary">Try different styles, wallpapers, clocks, and more</string>
<!-- Display settings screen, trigger for screen saver options -->
<string name="screensaver_settings_title">Screen saver</string>
@@ -7264,6 +7274,8 @@
<string name="keywords_profile_challenge">work challenge, work, profile</string>
<string name="keywords_unification">work profile, managed profile, unify, unification, work, profile</string>
<string name="keywords_gesture">gestures</string>
<!-- Search keywords for Global Actions Panel. [DO NOT TRANSLATE] -->
<string name="keywords_global_actions_panel" translatable="false">global actions</string>
<string name="keywords_payment_settings">pay, tap, payments</string>
<string name="keywords_backup">backup, back up</string>
<string name="keywords_assist_gesture_launch">gesture</string>
@@ -10148,6 +10160,15 @@
<!-- Summary text for ambient display tap [CHAR LIMIT=NONE]-->
<string name="ambient_display_tap_screen_summary">To check time, notifications, and other info, tap your screen.</string>
<!-- Summary text for global actions panel [CHAR LIMIT=NONE] [DO NOT TRANSLATE]-->
<string name="global_actions_panel_summary" translatable="false">To show the global actions panel, press &amp; hold Power button</string>
<!-- Preference and settings suggestion title text for global actions panel [CHAR LIMIT=60] [DO NOT TRANSLATE]-->
<string name="global_actions_panel_title" translatable="false">Show global actions</string>
<!-- Short title text for global actions panel [CHAR LIMIT=40] [DO NOT TRANSLATE]-->
<string name="global_actions_panel_short_title" translatable="false">Global actions</string>
<!-- Footer text for global actions panel [CHAR LIMIT=NONE] [DO NOT TRANSLATE]-->
<string name="global_actions_panel_footer" translatable="false">The global actions panel can be accessed even when the device is locked.</string>
<!-- Title text for swiping downwards on fingerprint sensor for notifications [CHAR LIMIT=80]-->
<string name="fingerprint_swipe_for_notifications_title">Swipe fingerprint for notifications</string>
<!-- Title text for fingerprint gesture preference screen [CHAR LIMIT=25] -->

View File

@@ -197,9 +197,8 @@
<item name="colorPrimaryDark">@*android:color/primary_dark_device_default_settings_light</item>
<item name="android:windowLightStatusBar">true</item>
<item name="android:navigationBarDividerColor">@*android:color/ripple_material_light</item>
<item name="android:navigationBarColor">@android:color/white</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowBackground">@android:color/white</item>
<item name="android:windowLightNavigationBar">true</item>
</style>
<!-- Note that Dialog themes do not set list dividers -->

View File

@@ -75,4 +75,10 @@
android:fragment="com.android.settings.gestures.PreventRingingGestureSettings"
settings:controller="com.android.settings.gestures.PreventRingingParentPreferenceController" />
<Preference
android:key="gesture_global_actions_panel_summary"
android:title="@string/global_actions_panel_short_title"
android:fragment="com.android.settings.gestures.GlobalActionsPanelSettings"
settings:controller="com.android.settings.gestures.GlobalActionsPanelPreferenceController" />
</PreferenceScreen>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2019 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:key="gesture_global_actions_panel"
android:title="@string/global_actions_panel_title">
<com.android.settings.widget.VideoPreference
android:key="global_actions_panel_video"
app:animation="@raw/gesture_global_actions_panel" />
<SwitchPreference
android:key="gesture_global_actions_panel_switch"
android:title="@string/global_actions_panel_title"
android:summary="@string/global_actions_panel_summary"
app:keywords="@string/keywords_global_actions_panel"
app:controller="com.android.settings.gestures.GlobalActionsPanelPreferenceController"
app:allowDividerAbove="true" />
<com.android.settingslib.widget.FooterPreference
android:key="footer_preference"
android:title="@string/global_actions_panel_footer" />
</PreferenceScreen>

View File

@@ -81,6 +81,14 @@ public interface ApplicationFeatureProvider {
*/
Set<String> getKeepEnabledPackages();
/**
* Returns a user readable text explaining how much time user has spent in an app at a
* pre-specified duration.
*/
default CharSequence getTimeSpentInApp(String packageName) {
return null;
}
/**
* Callback that receives the number of packages installed on the device.
*/

View File

@@ -41,7 +41,7 @@ import java.util.Set;
public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvider {
private final Context mContext;
protected final Context mContext;
private final PackageManager mPm;
private final IPackageManager mPms;
private final DevicePolicyManager mDpm;

View File

@@ -28,7 +28,9 @@ import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import java.util.List;
@@ -38,13 +40,15 @@ public class TimeSpentInAppPreferenceController extends BasePreferenceController
static final Intent SEE_TIME_IN_APP_TEMPLATE = new Intent(Settings.ACTION_APP_USAGE_SETTINGS);
private final PackageManager mPackageManager;
private final ApplicationFeatureProvider mAppFeatureProvider;
private Intent mIntent;
private String mPackageName;
public TimeSpentInAppPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mPackageManager = context.getPackageManager();
mAppFeatureProvider = FeatureFactory.getFactory(context)
.getApplicationFeatureProvider(context);
}
public void setPackageName(String packageName) {
@@ -80,6 +84,11 @@ public class TimeSpentInAppPreferenceController extends BasePreferenceController
}
}
@Override
public CharSequence getSummary() {
return mAppFeatureProvider.getTimeSpentInApp(mPackageName);
}
private boolean isSystemApp(ResolveInfo info) {
return info != null
&& info.activityInfo != null

View File

@@ -0,0 +1,175 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.settings.biometrics.face;
import static android.provider.Settings.Secure.FACE_UNLOCK_EDUCATION_INFO_DISPLAYED;
import static android.security.KeyStore.getApplicationContext;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.hardware.face.FaceManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.view.IllustrationVideoView;
public class FaceEnrollEducation extends BiometricEnrollBase {
private static final String TAG = "FaceEducation";
private static final int ON = 1;
private static final int OFF = 0;
// 10 seconds.
private static final long FACE_ENROLL_EDUCATION_DELAY = 16000;
private FaceManager mFaceManager;
private FaceEnrollAccessibilityToggle mSwitchDiversity;
private IllustrationVideoView mIllustrationNormal;
private View mIllustrationAccessibility;
private Handler mHandler;
private CompoundButton.OnCheckedChangeListener mSwitchDiversityListener =
new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
mIllustrationNormal.stop();
mIllustrationNormal.setVisibility(View.INVISIBLE);
mIllustrationAccessibility.setVisibility(View.VISIBLE);
} else {
mIllustrationNormal.setVisibility(View.VISIBLE);
mIllustrationNormal.start();
mIllustrationAccessibility.setVisibility(View.INVISIBLE);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.face_enroll_education);
getLayout().setHeaderText(R.string.security_settings_face_enroll_education_title);
setTitle(R.string.security_settings_face_enroll_education_title);
mHandler = new Handler();
mFaceManager = Utils.getFaceManagerOrNull(this);
final Button accessibilityButton = findViewById(R.id.accessibility_button);
accessibilityButton.setOnClickListener(view -> {
mSwitchDiversity.setChecked(true);
accessibilityButton.setVisibility(View.GONE);
mSwitchDiversity.setVisibility(View.VISIBLE);
});
mSwitchDiversity = findViewById(R.id.toggle_diversity);
mSwitchDiversity.setListener(mSwitchDiversityListener);
mIllustrationNormal = findViewById(R.id.illustration_normal);
mIllustrationAccessibility = findViewById(R.id.illustration_accessibility);
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
mFooterBarMixin.setSecondaryButton(
new FooterButton.Builder(this)
.setText(R.string.security_settings_face_enroll_enrolling_skip)
.setListener(this::onSkipButtonClick)
.setButtonType(FooterButton.ButtonType.SKIP)
.setTheme(R.style.SudGlifButton_Secondary)
.build()
);
final FooterButton footerButton = new FooterButton.Builder(this)
.setText(R.string.wizard_next)
.setListener(this::onNextButtonClick)
.setButtonType(FooterButton.ButtonType.NEXT)
.setTheme(R.style.SudGlifButton_Primary)
.build();
mFooterBarMixin.setPrimaryButton(footerButton);
final Context context = getApplicationContext();
final boolean didDisplayEdu = Settings.Secure.getIntForUser(context.getContentResolver(),
FACE_UNLOCK_EDUCATION_INFO_DISPLAYED, OFF, mUserId) == ON;
if (!didDisplayEdu) {
Settings.Secure.putIntForUser(context.getContentResolver(),
FACE_UNLOCK_EDUCATION_INFO_DISPLAYED, ON, mUserId);
footerButton.setEnabled(false);
mHandler.postDelayed(() -> {
footerButton.setEnabled(true);
}, FACE_ENROLL_EDUCATION_DELAY);
}
}
@Override
protected void onResume() {
super.onResume();
mSwitchDiversityListener.onCheckedChanged(mSwitchDiversity.getSwitch(),
mSwitchDiversity.isChecked());
}
@Override
protected void onNextButtonClick(View view) {
final Intent intent = new Intent();
if (mToken != null) {
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
}
if (mUserId != UserHandle.USER_NULL) {
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
}
final String flattenedString = getString(R.string.config_face_enroll);
if (!TextUtils.isEmpty(flattenedString)) {
ComponentName componentName = ComponentName.unflattenFromString(flattenedString);
intent.setComponent(componentName);
} else {
intent.setClass(this, FaceEnrollEnrolling.class);
}
intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
startActivityForResult(intent, BIOMETRIC_FIND_SENSOR_REQUEST);
}
protected void onSkipButtonClick(View view) {
setResult(RESULT_SKIP);
finish();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) {
setResult(resultCode);
finish();
}
}
@Override
public int getMetricsCategory() {
return SettingsEnums.FACE_ENROLL_INTRO;
}
}

View File

@@ -18,14 +18,9 @@ package com.android.settings.biometrics.face;
import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
import android.content.Intent;
import android.hardware.face.FaceManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.TextView;
import com.android.settings.R;
@@ -38,51 +33,18 @@ import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.span.LinkSpan;
import com.google.android.setupdesign.view.IllustrationVideoView;
public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
private static final String TAG = "FaceIntro";
private FaceManager mFaceManager;
private FaceEnrollAccessibilityToggle mSwitchDiversity;
private IllustrationVideoView mIllustrationNormal;
private View mIllustrationAccessibility;
private CompoundButton.OnCheckedChangeListener mSwitchDiversityListener =
new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
mIllustrationNormal.stop();
mIllustrationNormal.setVisibility(View.INVISIBLE);
mIllustrationAccessibility.setVisibility(View.VISIBLE);
} else {
mIllustrationNormal.setVisibility(View.VISIBLE);
mIllustrationNormal.start();
mIllustrationAccessibility.setVisibility(View.INVISIBLE);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mFaceManager = Utils.getFaceManagerOrNull(this);
final Button accessibilityButton = findViewById(R.id.accessibility_button);
accessibilityButton.setOnClickListener(view -> {
mSwitchDiversity.setChecked(true);
accessibilityButton.setVisibility(View.GONE);
mSwitchDiversity.setVisibility(View.VISIBLE);
});
mSwitchDiversity = findViewById(R.id.toggle_diversity);
mSwitchDiversity.setListener(mSwitchDiversityListener);
mIllustrationNormal = findViewById(R.id.illustration_normal);
mIllustrationAccessibility = findViewById(R.id.illustration_accessibility);
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
@@ -115,13 +77,6 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
);
}
@Override
protected void onResume() {
super.onResume();
mSwitchDiversityListener.onCheckedChanged(mSwitchDiversity.getSwitch(),
mSwitchDiversity.isChecked());
}
@Override
protected boolean isDisabledByAdmin() {
return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
@@ -200,16 +155,7 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
@Override
protected Intent getEnrollingIntent() {
final String flattenedString = getString(R.string.config_face_enroll);
final Intent intent = new Intent();
if (!TextUtils.isEmpty(flattenedString)) {
ComponentName componentName = ComponentName.unflattenFromString(flattenedString);
intent.setComponent(componentName);
} else {
intent.setClass(this, FaceEnrollEnrolling.class);
}
intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
Intent intent = new Intent(this, FaceEnrollEducation.class);
WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
return intent;
}

View File

@@ -33,4 +33,9 @@ public class SettingsUIDeviceConfig {
* {@code true} if near by device suggestion is enabled in connected device page
*/
public static final String BT_NEAR_BY_SUGGESTION_ENABLED = "bt_near_by_suggestion_enabled";
/**
* {@code true} whether or not event_log for generic actions is enabled. Default is true.
*/
public static final String GENERIC_EVENT_LOGGING_ENABLED = "event_logging_enabled";
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.core.instrumentation;
import android.content.Context;
import android.provider.DeviceConfig;
import com.android.settings.core.SettingsUIDeviceConfig;
import com.android.settingslib.core.instrumentation.EventLogWriter;
public class SettingsEventLogWriter extends EventLogWriter {
@Override
public void visible(Context context, int source, int category) {
if (shouldDisableGenericEventLogging()) {
return;
}
super.visible(context, source, category);
}
@Override
public void hidden(Context context, int category) {
if (shouldDisableGenericEventLogging()) {
return;
}
super.hidden(context, category);
}
@Override
public void action(Context context, int category, String pkg) {
if (shouldDisableGenericEventLogging()) {
return;
}
super.action(context, category, pkg);
}
@Override
public void action(Context context, int category, int value) {
if (shouldDisableGenericEventLogging()) {
return;
}
super.action(context, category, value);
}
@Override
public void action(Context context, int category, boolean value) {
if (shouldDisableGenericEventLogging()) {
return;
}
super.action(context, category, value);
}
private static boolean shouldDisableGenericEventLogging() {
return !DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
SettingsUIDeviceConfig.GENERIC_EVENT_LOGGING_ENABLED, true /* default */);
}
}

View File

@@ -17,14 +17,29 @@
package com.android.settings.core.instrumentation;
import android.content.Context;
import android.util.Log;
import android.util.Pair;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
public class SettingsMetricsFeatureProvider extends MetricsFeatureProvider {
private static final String TAG = "SettingsMetricsFeature";
@Override
protected void installLogWriters() {
super.installLogWriters();
mLoggerWriters.add(new StatsLogWriter());
mLoggerWriters.add(new SettingsEventLogWriter());
mLoggerWriters.add(new SettingsIntelligenceLogWriter());
}
/**
* @deprecated Use {@link #action(int, int, int, String, int)} instead.
*/
@Deprecated
@Override
public void action(Context context, int category, Pair<Integer, Object>... taggedData) {
Log.w(TAG, "action(Pair<Integer, Object>... taggedData) is deprecated, "
+ "Use action(int, int, int, String, int) instead.");
super.action(context, category, taggedData);
}
}

View File

@@ -178,9 +178,10 @@ public final class DataUsageUtils {
* Returns the default network template based on the availability of mobile data, Wifi. Returns
* ethernet template if both mobile data and Wifi are not available.
*/
static NetworkTemplate getDefaultTemplate(Context context, int defaultSubId) {
public static NetworkTemplate getDefaultTemplate(Context context, int defaultSubId) {
if (hasMobileData(context) && defaultSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
TelephonyManager telephonyManager = TelephonyManager.from(context);
TelephonyManager telephonyManager = TelephonyManager.from(context)
.createForSubscriptionId(defaultSubId);
NetworkTemplate mobileAll = NetworkTemplate.buildTemplateMobileAll(
telephonyManager.getSubscriberId(defaultSubId));
return NetworkTemplate.normalize(mobileAll,

View File

@@ -187,6 +187,14 @@ public abstract class StorageWizardBase extends FragmentActivity {
mNext.setVisibility(View.VISIBLE);
}
protected void setBackButtonVisibility(int visible) {
mBack.setVisibility(visible);
}
protected void setNextButtonVisibility(int visible) {
mNext.setVisibility(visible);
}
protected void setIcon(int resId) {
final GlifLayout layout = getGlifLayout();
final Drawable icon = getDrawable(resId).mutate();

View File

@@ -30,6 +30,7 @@ import android.os.SystemProperties;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.android.settings.R;
@@ -59,7 +60,8 @@ public class StorageWizardFormatProgress extends StorageWizardBase {
setHeaderText(R.string.storage_wizard_format_progress_title, getDiskShortDescription());
setBodyText(R.string.storage_wizard_format_progress_body, getDiskDescription());
setBackButtonVisibility(View.INVISIBLE);
setNextButtonVisibility(View.INVISIBLE);
mTask = (PartitionTask) getLastCustomNonConfigurationInstance();
if (mTask == null) {
mTask = new PartitionTask();

View File

@@ -51,7 +51,7 @@ public class StorageWizardInit extends StorageWizardBase {
mInternal = requireViewById(R.id.storage_wizard_init_internal);
setBackButtonText(R.string.storage_wizard_init_v2_later);
setNextButtonVisibility(View.INVISIBLE);
if (!mDisk.isAdoptable()) {
// If not adoptable, we only have one choice
mInternal.setEnabled(false);

View File

@@ -28,6 +28,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.storage.DiskInfo;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.android.settings.R;
@@ -51,7 +52,8 @@ public class StorageWizardMigrateProgress extends StorageWizardBase {
setIcon(R.drawable.ic_swap_horiz);
setHeaderText(R.string.storage_wizard_migrate_progress_v2_title);
setAuxChecklist();
setBackButtonVisibility(View.INVISIBLE);
setNextButtonVisibility(View.INVISIBLE);
// Register for updates and push through current status
getPackageManager().registerMoveCallback(mCallback, new Handler());
mCallback.onStatusChanged(mMoveId, getPackageManager().getMoveStatus(mMoveId), -1);

View File

@@ -73,6 +73,7 @@ public class StorageWizardMoveConfirm extends StorageWizardBase {
setBodyText(R.string.storage_wizard_move_confirm_body, appName, volumeName);
setNextButtonText(R.string.move_app);
setBackButtonVisibility(View.INVISIBLE);
}
@Override

View File

@@ -26,6 +26,7 @@ import android.content.pm.PackageManager.MoveCallback;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.android.settings.R;
@@ -49,7 +50,8 @@ public class StorageWizardMoveProgress extends StorageWizardBase {
setIcon(R.drawable.ic_swap_horiz);
setHeaderText(R.string.storage_wizard_move_progress_title, appName);
setBodyText(R.string.storage_wizard_move_progress_body, volumeName, appName);
setBackButtonVisibility(View.INVISIBLE);
setNextButtonVisibility(View.INVISIBLE);
// Register for updates and push through current status
getPackageManager().registerMoveCallback(mCallback, new Handler());
mCallback.onStatusChanged(mMoveId, getPackageManager().getMoveStatus(mMoveId), -1);

View File

@@ -50,6 +50,7 @@ public class StorageWizardReady extends StorageWizardBase {
}
setNextButtonText(R.string.done);
setBackButtonVisibility(View.INVISIBLE);
}
@Override

View File

@@ -20,9 +20,6 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.Settings;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
@@ -60,10 +57,12 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle
@Override
@AvailabilityStatus
public int getAvailabilityStatus() {
return mContext.getResources().getBoolean(
com.android.internal.R.bool.config_adaptive_sleep_available)
? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
final boolean supportedOnDevice = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_adaptive_sleep_available);
if (!supportedOnDevice) {
return UNSUPPORTED_ON_DEVICE;
}
return hasSufficientPermissions ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
}
@Override
@@ -77,15 +76,4 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle
? R.string.adaptive_sleep_summary_on
: R.string.adaptive_sleep_summary_off);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
final Preference preference = screen.findPreference(SYSTEM_KEY);
if (preference != null) {
preference.setEnabled(hasSufficientPermissions);
}
}
}

View File

@@ -13,17 +13,34 @@
*/
package com.android.settings.display;
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.hardware.display.ColorDisplayManager;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings.Secure;
import android.provider.Settings.System;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settings.core.TogglePreferenceController;
public class DisplayWhiteBalancePreferenceController extends TogglePreferenceController {
public class DisplayWhiteBalancePreferenceController extends TogglePreferenceController
implements LifecycleObserver, OnStart, OnStop {
private ColorDisplayManager mColorDisplayManager;
@VisibleForTesting
ContentObserver mContentObserver;
private Preference mPreference;
public DisplayWhiteBalancePreferenceController(Context context, String key) {
super(context, key);
@@ -31,12 +48,8 @@ public class DisplayWhiteBalancePreferenceController extends TogglePreferenceCon
@Override
public int getAvailabilityStatus() {
// Display white balance is only valid in linear light space. COLOR_MODE_SATURATED implies
// unmanaged color mode, and hence unknown color processing conditions.
return ColorDisplayManager.isDisplayWhiteBalanceAvailable(mContext) &&
getColorDisplayManager().getColorMode() !=
ColorDisplayManager.COLOR_MODE_SATURATED ?
AVAILABLE : DISABLED_FOR_USER;
return getColorDisplayManager().isDisplayWhiteBalanceAvailable(mContext) ?
AVAILABLE : DISABLED_FOR_USER;
}
@Override
@@ -49,6 +62,50 @@ public class DisplayWhiteBalancePreferenceController extends TogglePreferenceCon
return getColorDisplayManager().setDisplayWhiteBalanceEnabled(isChecked);
}
@Override
public void onStart() {
if (!isAvailable()) {
return;
}
final ContentResolver cr = mContext.getContentResolver();
mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
updateVisibility();
}
};
cr.registerContentObserver(
Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED),
false /* notifyForDescendants */, mContentObserver,
ActivityManager.getCurrentUser());
cr.registerContentObserver(
Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED),
false /* notifyForDescendants */, mContentObserver,
ActivityManager.getCurrentUser());
cr.registerContentObserver(
System.getUriFor(System.DISPLAY_COLOR_MODE),
false /* notifyForDescendants */, mContentObserver,
ActivityManager.getCurrentUser());
updateVisibility();
}
@Override
public void onStop() {
if (mContentObserver != null) {
mContext.getContentResolver().unregisterContentObserver(mContentObserver);
mContentObserver = null;
}
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = screen.findPreference(getPreferenceKey());
}
@VisibleForTesting
ColorDisplayManager getColorDisplayManager() {
if (mColorDisplayManager == null) {
@@ -56,4 +113,17 @@ public class DisplayWhiteBalancePreferenceController extends TogglePreferenceCon
}
return mColorDisplayManager;
}
@VisibleForTesting
void updateVisibility() {
if (mPreference != null) {
ColorDisplayManager cdm = getColorDisplayManager();
// Display white balance is only valid in linear light space. COLOR_MODE_SATURATED
// implies unmanaged color mode, and hence unknown color processing conditions.
// We also disallow display white balance when color accessibility features are enabled.
mPreference.setVisible(cdm.getColorMode() != ColorDisplayManager.COLOR_MODE_SATURATED &&
!cdm.areAccessibilityTransformsEnabled(mContext));
}
}
}

View File

@@ -378,6 +378,9 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
@VisibleForTesting
void restartBatteryInfoLoader() {
if (getContext() == null) {
return;
}
getLoaderManager().restartLoader(BATTERY_INFO_LOADER, Bundle.EMPTY,
mBatteryInfoLoaderCallbacks);
if (mPowerFeatureProvider.isEstimateDebugEnabled()) {

View File

@@ -99,10 +99,15 @@ public class BatterySaverScheduleSeekBarController implements
}
}
/**
* Adds the seekbar to the end of the provided preference screen
*
* @param screen The preference screen to add the seekbar to
*/
public void addToScreen(PreferenceScreen screen) {
// makes sure it gets added after the preferences if called due to first time battery
// saver message
mSeekBarPreference.setOrder(5);
mSeekBarPreference.setOrder(100);
screen.addPreference(mSeekBarPreference);
}
}

View File

@@ -64,6 +64,7 @@ public class BatterySaverScheduleSettings extends RadioButtonPickerFragment {
final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange, Uri uri) {
getPreferenceScreen().removeAll();
updateCandidates();
}
};

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.settings.gestures;
import android.content.Context;
import android.provider.Settings;
import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
public class GlobalActionsPanelPreferenceController extends GesturePreferenceController {
private static final String PREF_KEY_VIDEO = "global_actions_panel_video";
@VisibleForTesting
protected static final String ENABLED_SETTING = Settings.Secure.GLOBAL_ACTIONS_PANEL_ENABLED;
@VisibleForTesting
protected static final String AVAILABLE_SETTING =
Settings.Secure.GLOBAL_ACTIONS_PANEL_AVAILABLE;
@VisibleForTesting
protected static final String TOGGLE_KEY = "gesture_global_actions_panel_switch";
public GlobalActionsPanelPreferenceController(Context context, String key) {
super(context, key);
}
@Override
public int getAvailabilityStatus() {
int enabled = Settings.Secure.getInt(mContext.getContentResolver(), AVAILABLE_SETTING, 0);
return enabled == 1 ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
public boolean setChecked(boolean isChecked) {
return Settings.Secure.putInt(mContext.getContentResolver(), ENABLED_SETTING,
isChecked ? 1 : 0);
}
@Override
protected String getVideoPrefKey() {
return PREF_KEY_VIDEO;
}
@Override
public boolean isSliceable() {
return TextUtils.equals(getPreferenceKey(), TOGGLE_KEY);
}
@Override
public boolean isChecked() {
int enabled = Settings.Secure.getInt(mContext.getContentResolver(), ENABLED_SETTING, 0);
return enabled == 1;
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.settings.gestures;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.provider.SearchIndexableResource;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
import java.util.Arrays;
import java.util.List;
@SearchIndexable
public class GlobalActionsPanelSettings extends DashboardFragment {
private static final String TAG = "GlobalActionsPanelSettings";
@Override
public int getMetricsCategory() {
return SettingsEnums.GLOBAL_ACTIONS_PANEL_SETTINGS;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.global_actions_panel_settings;
}
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.global_actions_panel_settings;
return Arrays.asList(sir);
}
};
}

View File

@@ -39,7 +39,7 @@ public class SystemNavigationEdgeToEdgePreferenceController extends
@VisibleForTesting
public SystemNavigationEdgeToEdgePreferenceController(Context context,
IOverlayManager overlayManager, String key) {
super(context, overlayManager, key);
super(context, overlayManager, key, NAV_BAR_MODE_GESTURAL_OVERLAY);
}
@Override

View File

@@ -39,7 +39,7 @@ public class SystemNavigationLegacyPreferenceController extends
@VisibleForTesting
public SystemNavigationLegacyPreferenceController(Context context,
IOverlayManager overlayManager, String key) {
super(context, overlayManager, key);
super(context, overlayManager, key, NAV_BAR_MODE_3BUTTON_OVERLAY);
}
@Override

View File

@@ -52,16 +52,18 @@ public abstract class SystemNavigationPreferenceController extends GesturePrefer
protected final IOverlayManager mOverlayManager;
protected PreferenceScreen mPreferenceScreen;
private final String mOverlayPackage;
public SystemNavigationPreferenceController(Context context, IOverlayManager overlayManager,
String key) {
String key, String overlayPackage) {
super(context, key);
mOverlayManager = overlayManager;
mOverlayPackage = overlayPackage;
}
@Override
public int getAvailabilityStatus() {
return isGestureAvailable(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
return isGestureAvailable(mContext, mOverlayPackage) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
@@ -105,23 +107,43 @@ public abstract class SystemNavigationPreferenceController extends GesturePrefer
return PREF_KEY_VIDEO;
}
static boolean isGestureAvailable(Context context) {
return isGestureAvailable(context, null /* overlayPackage */);
}
static boolean isGestureAvailable(Context context, String overlayPackage) {
// Skip if the swipe up settings are not available
if (!context.getResources().getBoolean(
com.android.internal.R.bool.config_swipe_up_gesture_setting_available)) {
return false;
}
// Skip if the recents component is not defined
final ComponentName recentsComponentName = ComponentName.unflattenFromString(
context.getString(com.android.internal.R.string.config_recentsComponentName));
if (recentsComponentName == null) {
return false;
}
// Skip if the overview proxy service exists
final PackageManager pm = context.getPackageManager();
final Intent quickStepIntent = new Intent(ACTION_QUICKSTEP)
.setPackage(recentsComponentName.getPackageName());
if (context.getPackageManager().resolveService(quickStepIntent,
PackageManager.MATCH_SYSTEM_ONLY) == null) {
if (pm.resolveService(quickStepIntent, PackageManager.MATCH_SYSTEM_ONLY) == null) {
return false;
}
// Skip if the required overlay package is defined but doesn't exist
if (overlayPackage != null) {
try {
return pm.getPackageInfo(overlayPackage, 0 /* flags */) != null;
} catch (PackageManager.NameNotFoundException e) {
// Not found, just return unavailable
return false;
}
}
return true;
}

View File

@@ -39,7 +39,7 @@ public class SystemNavigationSwipeUpPreferenceController extends
@VisibleForTesting
public SystemNavigationSwipeUpPreferenceController(Context context,
IOverlayManager overlayManager, String key) {
super(context, overlayManager, key);
super(context, overlayManager, key, NAV_BAR_MODE_2BUTTON_OVERLAY);
}
@Override

View File

@@ -42,8 +42,11 @@ public class SettingsHomepageActivity extends SettingsBaseActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
updateWindowProperties();
setContentView(R.layout.settings_homepage_container);
final View root = findViewById(R.id.settings_homepage_container);
root.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
setHomepageContainerPaddingTop();
final Toolbar toolbar = findViewById(R.id.search_action_bar);
@@ -76,29 +79,15 @@ public class SettingsHomepageActivity extends SettingsBaseActivity {
fragmentTransaction.commit();
}
private void updateWindowProperties() {
final View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
decorView.getSystemUiVisibility() |
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
);
getWindow().setStatusBarColor(getColor(R.color.homepage_status_bar_color));
}
@VisibleForTesting
void setHomepageContainerPaddingTop() {
final View view = this.findViewById(R.id.homepage_container);
final int statusBarHeight = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
final int searchBarHeight = getResources().getDimensionPixelSize(R.dimen.search_bar_height);
final int searchBarMargin = getResources().getDimensionPixelSize(R.dimen.search_bar_margin);
// The top padding is the height of status bar + height of action bar(48dp) + top/bottom
// margins(16dp)
final int paddingTop = statusBarHeight + searchBarHeight + searchBarMargin * 2;
// The top padding is the height of action bar(48dp) + top/bottom margins(16dp)
final int paddingTop = searchBarHeight + searchBarMargin * 2;
view.setPadding(0 /* left */, paddingTop, 0 /* right */, 0 /* bottom */);
}
}

View File

@@ -112,8 +112,10 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, Life
final View swipeBackground = holder.itemView.findViewById(R.id.dismissal_swipe_background);
sliceLiveData.removeObservers(mLifecycleOwner);
// set the background to Gone in case the holder is reused.
swipeBackground.setVisibility(View.GONE);
// set the background to GONE in case the holder is reused.
if (swipeBackground != null) {
swipeBackground.setVisibility(View.GONE);
}
sliceLiveData.observe(mLifecycleOwner, slice -> {
if (slice == null) {
Log.w(TAG, "Slice is null");
@@ -140,8 +142,9 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, Life
default:
mFullCardHelper.bindView(holder, card, slice);
}
swipeBackground.setVisibility(View.VISIBLE);
if (swipeBackground != null) {
swipeBackground.setVisibility(View.VISIBLE);
}
});
switch (holder.getItemViewType()) {

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.settings.network;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
/** Helper class to listen for changes in the enabled state of mobile data. */
public class MobileDataEnabledListener extends ContentObserver {
private Context mContext;
private Client mClient;
private int mSubId;
public interface Client {
void onMobileDataEnabledChange();
}
public MobileDataEnabledListener(Context context, Client client) {
super(new Handler());
mContext = context;
mClient = client;
mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
/** Starts listening to changes in the enabled state for data on the given subscription id. */
public void start(int subId) {
mSubId = subId;
Uri uri;
if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA);
} else {
uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + mSubId);
}
mContext.getContentResolver().registerContentObserver(uri, true /*notifyForDescendants*/,
this);
}
public int getSubId() {
return mSubId;
}
public MobileDataEnabledListener stop() {
mContext.getContentResolver().unregisterContentObserver(this);
return this;
}
@Override
public void onChange(boolean selfChange) {
mClient.onMobileDataEnabledChange();
}
}

View File

@@ -21,6 +21,9 @@ import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -35,6 +38,7 @@ import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.network.telephony.DataConnectivityListener;
import com.android.settings.network.telephony.MobileNetworkActivity;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -46,14 +50,18 @@ import java.util.Map;
* available if there are 2 or more subscriptions.
*/
public class SubscriptionsPreferenceController extends AbstractPreferenceController implements
LifecycleObserver, SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
LifecycleObserver, SubscriptionsChangeListener.SubscriptionsChangeListenerClient,
MobileDataEnabledListener.Client, DataConnectivityListener.Client {
private static final String TAG = "SubscriptionsPrefCntrlr";
private UpdateListener mUpdateListener;
private String mPreferenceGroupKey;
private PreferenceGroup mPreferenceGroup;
private SubscriptionManager mManager;
private ConnectivityManager mConnectivityManager;
private SubscriptionsChangeListener mSubscriptionsListener;
private MobileDataEnabledListener mDataEnabledListener;
private DataConnectivityListener mConnectivityListener;
// Map of subscription id to Preference
private Map<Integer, Preference> mSubscriptionPreferences;
@@ -89,20 +97,27 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
mPreferenceGroupKey = preferenceGroupKey;
mStartOrder = startOrder;
mManager = context.getSystemService(SubscriptionManager.class);
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
mSubscriptionPreferences = new ArrayMap<>();
mSubscriptionsListener = new SubscriptionsChangeListener(context, this);
mDataEnabledListener = new MobileDataEnabledListener(context, this);
mConnectivityListener = new DataConnectivityListener(context, this);
lifecycle.addObserver(this);
}
@OnLifecycleEvent(ON_RESUME)
public void onResume() {
mSubscriptionsListener.start();
mDataEnabledListener.start(SubscriptionManager.getDefaultDataSubscriptionId());
mConnectivityListener.start();
update();
}
@OnLifecycleEvent(ON_PAUSE)
public void onPause() {
mSubscriptionsListener.stop();
mDataEnabledListener.stop();
mConnectivityListener.stop();
}
@Override
@@ -158,6 +173,19 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
mUpdateListener.onChildrenUpdated();
}
private boolean activeNetworkIsCellular() {
final Network activeNetwork = mConnectivityManager.getActiveNetwork();
if (activeNetwork == null) {
return false;
}
final NetworkCapabilities networkCapabilities = mConnectivityManager.getNetworkCapabilities(
activeNetwork);
if (networkCapabilities == null) {
return false;
}
return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
}
/**
* The summary can have either 1 or 2 lines depending on which services (calls, SMS, data) this
* subscription is the default for.
@@ -187,10 +215,10 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
if (subId == dataDefaultSubId) {
final TelephonyManager telMgrForSub = mContext.getSystemService(
TelephonyManager.class).createForSubscriptionId(subId);
final int dataState = telMgrForSub.getDataState();
if (dataState == TelephonyManager.DATA_CONNECTED) {
boolean dataEnabled = telMgrForSub.isDataEnabled();
if (dataEnabled && activeNetworkIsCellular()) {
line2 = mContext.getString(R.string.mobile_data_active);
} else if (!telMgrForSub.isDataEnabled()) {
} else if (!dataEnabled) {
line2 = mContext.getString(R.string.mobile_data_off);
} else {
line2 = mContext.getString(R.string.default_for_mobile_data);
@@ -231,6 +259,22 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
@Override
public void onSubscriptionsChanged() {
// See if we need to change which sub id we're using to listen for enabled/disabled changes.
int defaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId();
if (defaultDataSubId != mDataEnabledListener.getSubId()) {
mDataEnabledListener.stop();
mDataEnabledListener.start(defaultDataSubId);
}
update();
}
@Override
public void onMobileDataEnabledChange() {
update();
}
@Override
public void onDataConnectivityChange() {
update();
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.settings.network.telephony;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
/** A helper class to listen to a few different kinds of connectivity changes that could be relevant
* to changes in which network is active, and whether the active network has internet data
* connectivity. */
public class DataConnectivityListener extends ConnectivityManager.NetworkCallback {
private Context mContext;
private ConnectivityManager mConnectivityManager;
private final NetworkRequest mNetworkRequest;
private Client mClient;
public interface Client {
void onDataConnectivityChange();
}
public DataConnectivityListener(Context context, Client client) {
mContext = context;
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
mClient = client;
mNetworkRequest = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
}
public void start() {
mConnectivityManager.registerNetworkCallback(mNetworkRequest, this,
mContext.getMainThreadHandler());
}
public void stop() {
mConnectivityManager.unregisterNetworkCallback(this);
}
@Override
public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
final Network activeNetwork = mConnectivityManager.getActiveNetwork();
if (activeNetwork != null && activeNetwork.equals(network)) {
mClient.onDataConnectivityChange();
}
}
@Override
public void onLosing(Network network, int maxMsToLive) {
mClient.onDataConnectivityChange();
}
@Override
public void onLost(Network network) {
mClient.onDataConnectivityChange();
}
}

View File

@@ -21,9 +21,7 @@ import android.content.Intent;
import android.net.NetworkTemplate;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.format.Formatter;
import androidx.preference.Preference;
@@ -87,9 +85,10 @@ public class DataUsagePreferenceController extends TelephonyBasePreferenceContro
mSubId = subId;
if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
mTemplate = getNetworkTemplate(mContext, subId);
mTemplate = DataUsageUtils.getDefaultTemplate(mContext, mSubId);
final DataUsageController controller = new DataUsageController(mContext);
controller.setSubscriptionId(mSubId);
mDataUsageInfo = controller.getDataUsageInfo(mTemplate);
mIntent = new Intent(Settings.ACTION_MOBILE_DATA_USAGE);
@@ -97,12 +96,4 @@ public class DataUsagePreferenceController extends TelephonyBasePreferenceContro
mIntent.putExtra(Settings.EXTRA_SUB_ID, mSubId);
}
}
private NetworkTemplate getNetworkTemplate(Context context, int subId) {
final TelephonyManager tm = TelephonyManager.from(context).createForSubscriptionId(subId);
NetworkTemplate mobileAll = NetworkTemplate.buildTemplateMobileAll(tm.getSubscriberId());
return NetworkTemplate.normalize(mobileAll, tm.getMergedSubscriberIds());
}
}

View File

@@ -33,7 +33,6 @@ import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
@@ -114,8 +113,10 @@ public class RoamingPreferenceController extends TelephonyTogglePreferenceContro
public void updateState(Preference preference) {
super.updateState(preference);
final RestrictedSwitchPreference switchPreference = (RestrictedSwitchPreference) preference;
switchPreference.setEnabled(mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID);
switchPreference.setChecked(isChecked());
if (!switchPreference.isDisabledByAdmin()) {
switchPreference.setEnabled(mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID);
switchPreference.setChecked(isChecked());
}
}
@VisibleForTesting

View File

@@ -20,6 +20,8 @@ import static android.content.Intent.EXTRA_PACKAGE_NAME;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -32,6 +34,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
import org.junit.Test;
@@ -58,10 +61,12 @@ public class TimeSpentInAppPreferenceControllerTest {
private ShadowPackageManager mPackageManager;
private TimeSpentInAppPreferenceController mController;
private Preference mPreference;
private FakeFeatureFactory mFeatureFactory;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mFeatureFactory = FakeFeatureFactory.setupForTest();
mContext = RuntimeEnvironment.application;
mPackageManager = Shadows.shadowOf(mContext.getPackageManager());
mController = new TimeSpentInAppPreferenceController(mContext, TEST_KEY);
@@ -112,4 +117,12 @@ public class TimeSpentInAppPreferenceControllerTest {
assertThat(intent.getStringExtra(EXTRA_PACKAGE_NAME))
.isEqualTo(TEST_INTENT.getStringExtra(EXTRA_PACKAGE_NAME));
}
@Test
public void getSummary_shouldQueryAppFeatureProvider() {
mController.getSummary();
verify(mFeatureFactory.applicationFeatureProvider).getTimeSpentInApp(
nullable(String.class));
}
}

View File

@@ -0,0 +1,122 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.core.instrumentation;
import static com.google.common.truth.Truth.assertThat;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.metrics.LogMaker;
import android.provider.DeviceConfig;
import com.android.internal.logging.MetricsLogger;
import com.android.settings.core.SettingsUIDeviceConfig;
import com.android.settings.testutils.shadow.ShadowDeviceConfig;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowDeviceConfig.class, SettingsEventLogWriterTest.ShadowMetricsLogger.class})
public class SettingsEventLogWriterTest {
private SettingsEventLogWriter mWriter;
@Before
public void setUp() {
mWriter = new SettingsEventLogWriter();
}
@After
public void tearDown() {
ShadowDeviceConfig.reset();
ShadowMetricsLogger.reset();
}
@Test
public void visible_eventLogEnabled_shouldLog() {
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
SettingsUIDeviceConfig.GENERIC_EVENT_LOGGING_ENABLED, "true", true);
mWriter.visible(RuntimeEnvironment.application, SettingsEnums.PAGE_UNKNOWN,
SettingsEnums.SETTINGS_HOMEPAGE);
assertThat(ShadowMetricsLogger.sActionLoggedCount).isEqualTo(1);
}
@Test
public void hidden_eventLogEnabled_shouldLog() {
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
SettingsUIDeviceConfig.GENERIC_EVENT_LOGGING_ENABLED, "true", true);
mWriter.hidden(RuntimeEnvironment.application, SettingsEnums.SETTINGS_HOMEPAGE);
assertThat(ShadowMetricsLogger.sActionLoggedCount).isEqualTo(1);
}
@Test
public void visible_eventLogDisabled_shouldNotLog() {
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
SettingsUIDeviceConfig.GENERIC_EVENT_LOGGING_ENABLED, "false", true);
mWriter.visible(RuntimeEnvironment.application, SettingsEnums.PAGE_UNKNOWN,
SettingsEnums.SETTINGS_HOMEPAGE);
assertThat(ShadowMetricsLogger.sActionLoggedCount).isEqualTo(0);
}
@Test
public void hidden_eventLogDisabled_shouldNotLog() {
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
SettingsUIDeviceConfig.GENERIC_EVENT_LOGGING_ENABLED, "false", true);
mWriter.hidden(RuntimeEnvironment.application, SettingsEnums.SETTINGS_HOMEPAGE);
assertThat(ShadowMetricsLogger.sActionLoggedCount).isEqualTo(0);
}
@Implements(MetricsLogger.class)
public static class ShadowMetricsLogger {
public static int sActionLoggedCount = 0;
@Resetter
public static void reset() {
sActionLoggedCount = 0;
}
@Implementation
protected static void action(LogMaker content) {
sActionLoggedCount++;
}
@Implementation
public static void hidden(Context context, int category) throws IllegalArgumentException {
sActionLoggedCount++;
}
}
}

View File

@@ -27,11 +27,13 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
import android.net.NetworkPolicyManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import androidx.fragment.app.FragmentActivity;
@@ -44,6 +46,7 @@ import com.android.settings.testutils.shadow.ShadowUtils;
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.Robolectric;
@@ -68,6 +71,8 @@ public class DataUsageSummaryTest {
private NetworkPolicyManager mNetworkPolicyManager;
@Mock
private NetworkStatsManager mNetworkStatsManager;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private TelephonyManager mTelephonyManager;
private Context mContext;
private FragmentActivity mActivity;
private SummaryLoader.SummaryProvider mSummaryProvider;
@@ -84,7 +89,9 @@ public class DataUsageSummaryTest {
ShadowUserManager.getShadow().setIsAdminUser(true);
shadowContext.setSystemService(Context.NETWORK_POLICY_SERVICE, mNetworkPolicyManager);
mContext = RuntimeEnvironment.application;
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
mActivity = spy(Robolectric.buildActivity(FragmentActivity.class).get());
doReturn(mNetworkStatsManager).when(mActivity).getSystemService(NetworkStatsManager.class);

View File

@@ -21,6 +21,8 @@ import static android.provider.Settings.System.ADAPTIVE_SLEEP;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
@@ -28,11 +30,12 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.Settings;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settingslib.RestrictedPreference;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -41,7 +44,6 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
@Ignore("b/130897305")
public class AdaptiveSleepPreferenceControllerTest {
private static final String PREFERENCE_KEY = "adaptive_sleep";
@@ -52,18 +54,25 @@ public class AdaptiveSleepPreferenceControllerTest {
@Mock
private PackageManager mPackageManager;
@Mock
private PreferenceScreen mScreen;
@Mock
private Preference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mContext = spy(RuntimeEnvironment.application);
mContentResolver = mContext.getContentResolver();
mController = new AdaptiveSleepPreferenceController(mContext, PREFERENCE_KEY);
doReturn(mPackageManager).when(mContext).getPackageManager();
when(mPackageManager.getAttentionServicePackageName()).thenReturn("some.package");
when(mPackageManager.checkPermission(any(), any())).thenReturn(
PackageManager.PERMISSION_GRANTED);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mController = new AdaptiveSleepPreferenceController(mContext, PREFERENCE_KEY);
}
@Test
@@ -145,8 +154,7 @@ public class AdaptiveSleepPreferenceControllerTest {
PackageManager.PERMISSION_DENIED);
mController.setChecked(true);
final RestrictedPreference mPreference = new RestrictedPreference(mContext);
mController.updateState(mPreference);
mController.displayPreference(mScreen);
assertThat(mPreference.isEnabled()).isFalse();
}
}

View File

@@ -1,16 +1,27 @@
package com.android.settings.display;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static com.google.common.truth.Truth.assertThat;
import android.content.ContentResolver;
import android.content.Context;
import android.hardware.display.ColorDisplayManager;
import android.provider.Settings;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import org.junit.After;
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;
@@ -27,6 +38,15 @@ public class DisplayWhiteBalancePreferenceControllerTest {
@Mock
private ColorDisplayManager mColorDisplayManager;
private ContentResolver mContentResolver;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@Mock
private PreferenceScreen mScreen;
@Mock
private Preference mPreference;
private final String PREFERENCE_KEY = "display_white_balance";
@After
public void tearDown() {
@@ -36,17 +56,21 @@ public class DisplayWhiteBalancePreferenceControllerTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mController = spy(new DisplayWhiteBalancePreferenceController(RuntimeEnvironment.application,
"display_white_balance"));
mContentResolver = RuntimeEnvironment.application.getContentResolver();
when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mContext.getResources()).thenReturn(RuntimeEnvironment.application.getResources());
when(mScreen.findPreference(PREFERENCE_KEY)).thenReturn(mPreference);
mController = spy(new DisplayWhiteBalancePreferenceController(mContext, PREFERENCE_KEY));
doReturn(mColorDisplayManager).when(mController).getColorDisplayManager();
}
@Test
public void isAvailable_configuredAvailable() {
public void isAvailable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
when(mColorDisplayManager.getColorMode())
.thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
assertThat(mController.isAvailable()).isTrue();
}
@@ -54,20 +78,7 @@ public class DisplayWhiteBalancePreferenceControllerTest {
public void isAvailable_configuredUnavailable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, false);
when(mColorDisplayManager.getColorMode())
.thenReturn(ColorDisplayManager.COLOR_MODE_SATURATED);
assertThat(mController.isAvailable()).isFalse();
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, false);
when(mColorDisplayManager.getColorMode())
.thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
assertThat(mController.isAvailable()).isFalse();
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
when(mColorDisplayManager.getColorMode())
.thenReturn(ColorDisplayManager.COLOR_MODE_SATURATED);
assertThat(mController.isAvailable()).isFalse();
}
@@ -94,4 +105,101 @@ public class DisplayWhiteBalancePreferenceControllerTest {
when(mColorDisplayManager.isDisplayWhiteBalanceEnabled()).thenReturn(false);
assertThat(mController.isChecked()).isFalse();
}
@Test
public void onStart_configuredUnavailable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, false);
mController.displayPreference(mScreen);
mController.onStart();
assertThat(mController.mContentObserver).isNull();
}
@Test
public void onStart_configuredAvailable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
when(mColorDisplayManager.getColorMode())
.thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
toggleAccessibilityInversion(false);
toggleAccessibilityDaltonizer(false);
mController.displayPreference(mScreen);
mController.onStart();
assertThat(mController.mContentObserver).isNotNull();
}
@Test
public void visibility_configuredAvailableAccessibilityToggled() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
mController.displayPreference(mScreen);
// Accessibility features disabled
toggleAccessibilityInversion(false);
reset(mPreference);
mController.updateVisibility();
verify(mPreference).setVisible(true);
toggleAccessibilityDaltonizer(false);
reset(mPreference);
mController.updateVisibility();
verify(mPreference).setVisible(true);
// Accessibility features enabled one by one
toggleAccessibilityInversion(true);
mController.updateVisibility();
verify(mPreference).setVisible(false);
toggleAccessibilityDaltonizer(true);
reset(mPreference);
mController.updateVisibility();
verify(mPreference).setVisible(false);
// Accessibility features disabled one by one
toggleAccessibilityInversion(false);
reset(mPreference);
mController.updateVisibility();
// Daltonizer is still enabled, so we expect the preference to still be invisible
verify(mPreference).setVisible(false);
// Now both a11y features are disabled, so we expect the preference to become visible
toggleAccessibilityDaltonizer(false);
mController.updateVisibility();
verify(mPreference).setVisible(true);
}
@Test
public void visibility_configuredAvailableColorModeChanged() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
mController.displayPreference(mScreen);
// Non-Saturated color mode selected
when(mColorDisplayManager.getColorMode()).thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
reset(mPreference);
mController.updateVisibility();
verify(mPreference).setVisible(true);
// Saturated color mode selected
when(mColorDisplayManager.getColorMode()).thenReturn(ColorDisplayManager.COLOR_MODE_SATURATED);
mController.updateVisibility();
verify(mPreference).setVisible(false);
// Switch back to non-Saturated color mode
when(mColorDisplayManager.getColorMode()).thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
reset(mPreference);
mController.updateVisibility();
verify(mPreference).setVisible(true);
}
private void toggleAccessibilityInversion(boolean enable) {
Settings.Secure.putInt(mContentResolver,
Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, enable ? 1 : 0);
}
private void toggleAccessibilityDaltonizer(boolean enable) {
Settings.Secure.putInt(mContentResolver,
Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, enable ? 1 : 0);
}
}

View File

@@ -15,6 +15,7 @@
*/
package com.android.settings.fuelgauge;
import static com.android.settings.fuelgauge.PowerUsageSummary.BATTERY_INFO_LOADER;
import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_ADVANCED_BATTERY;
import static com.google.common.truth.Truth.assertThat;
@@ -373,6 +374,17 @@ public class PowerUsageSummaryTest {
mFragment.mSettingsObserver);
}
@Test
public void restartBatteryInfoLoader_contextNull_doNothing() {
when(mFragment.getContext()).thenReturn(null);
when(mFragment.getLoaderManager()).thenReturn(mLoaderManager);
mFragment.restartBatteryInfoLoader();
verify(mLoaderManager, never()).restartLoader(BATTERY_INFO_LOADER, Bundle.EMPTY,
mFragment.mBatteryInfoLoaderCallbacks);
}
public static class TestFragment extends PowerUsageSummary {
private Context mContext;

View File

@@ -7,9 +7,14 @@ import android.content.Context;
import android.os.PowerManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import androidx.preference.PreferenceScreen;
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;
@@ -19,9 +24,12 @@ public class BatterySaverScheduleSeekBarControllerTest {
private Context mContext;
private ContentResolver mResolver;
private BatterySaverScheduleSeekBarController mController;
@Mock
private PreferenceScreen mScreen;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = new BatterySaverScheduleSeekBarController(mContext);
mResolver = mContext.getContentResolver();
@@ -62,4 +70,14 @@ public class BatterySaverScheduleSeekBarControllerTest {
mController.updateSeekBar();
assertThat(mController.mSeekBarPreference.isVisible()).isFalse();
}
@Test
public void addToScreen_addsToEnd() {
Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 15);
mController.addToScreen(mScreen);
assertThat(mController.mSeekBarPreference.getOrder()).isEqualTo(100);
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.settings.gestures;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.provider.Settings;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class GlobalActionsPanelPreferenceControllerTest {
private Context mContext;
private GlobalActionsPanelPreferenceController mController;
private static final String KEY_GESTURE_PANEL = "gesture_global_actions_panel";
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = new GlobalActionsPanelPreferenceController(mContext, KEY_GESTURE_PANEL);
}
@Test
public void testIsChecked_panelEnabled() {
Settings.Secure.putInt(
mContext.getContentResolver(), mController.ENABLED_SETTING, 1);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void testIsChecked_panelDisabled() {
Settings.Secure.putInt(
mContext.getContentResolver(), mController.ENABLED_SETTING, 0);
assertThat(mController.isChecked()).isFalse();
}
@Test
public void getAvailabilityStatus_panelAvailable() {
Settings.Secure.putInt(
mContext.getContentResolver(), mController.AVAILABLE_SETTING, 1);
assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE);
}
@Test
public void getAvailabilityStatus_panelUnavailable() {
Settings.Secure.putInt(
mContext.getContentResolver(), mController.AVAILABLE_SETTING, 0);
assertThat(mController.getAvailabilityStatus())
.isEqualTo(mController.CONDITIONALLY_UNAVAILABLE);
}
@Test
public void isSliceable_correctKey() {
final GlobalActionsPanelPreferenceController controller =
new GlobalActionsPanelPreferenceController(mContext, mController.TOGGLE_KEY);
assertThat(controller.isSliceable()).isTrue();
}
@Test
public void isSliceable_incorrectKey() {
final GlobalActionsPanelPreferenceController controller =
new GlobalActionsPanelPreferenceController(mContext, "bad_key");
assertThat(controller.isSliceable()).isFalse();
}
}

View File

@@ -130,6 +130,12 @@ public class SystemNavigationEdgeToEdgePreferenceControllerTest {
.isFalse();
}
@Test
public void testIsGestureAvailable_noOverlayPackage_shouldReturnFalse() {
assertThat(SystemNavigationEdgeToEdgePreferenceController.isGestureAvailable(mContext,
"com.package.fake")).isFalse();
}
@Test
public void testIsChecked_defaultIsEdgeToEdge_shouldReturnTrue() {
SettingsShadowResources.overrideResource(R.integer.config_navBarInteractionMode,

View File

@@ -130,6 +130,12 @@ public class SystemNavigationLegacyPreferenceControllerTest {
SystemNavigationLegacyPreferenceController.isGestureAvailable(mContext)).isFalse();
}
@Test
public void testIsGestureAvailable_noOverlayPackage_shouldReturnFalse() {
assertThat(SystemNavigationLegacyPreferenceController.isGestureAvailable(mContext,
"com.package.fake")).isFalse();
}
@Test
public void testIsChecked_defaultIsLegacy_shouldReturnTrue() {
SettingsShadowResources.overrideResource(R.integer.config_navBarInteractionMode,

View File

@@ -130,6 +130,12 @@ public class SystemNavigationSwipeUpPreferenceControllerTest {
.isFalse();
}
@Test
public void testIsGestureAvailable_noOverlayPackage_shouldReturnFalse() {
assertThat(SystemNavigationSwipeUpPreferenceController.isGestureAvailable(mContext,
"com.package.fake")).isFalse();
}
@Test
public void testIsChecked_defaultIsSwipeUp_shouldReturnTrue() {
SettingsShadowResources.overrideResource(R.integer.config_navBarInteractionMode,

View File

@@ -35,8 +35,6 @@ public class SettingsHomepageActivityTest {
public void setHomepageContainerPaddingTop_shouldBeSetPaddingTop() {
final SettingsHomepageActivity activity = Robolectric.buildActivity(
SettingsHomepageActivity.class).create().get();
final int statusBarHeight = activity.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
final int searchBarHeight = activity.getResources().getDimensionPixelSize(
R.dimen.search_bar_height);
final int searchBarMargin = activity.getResources().getDimensionPixelSize(
@@ -46,8 +44,7 @@ public class SettingsHomepageActivityTest {
activity.setHomepageContainerPaddingTop();
final int actualPaddingTop = view.getPaddingTop();
assertThat(actualPaddingTop).isEqualTo(
statusBarHeight + searchBarHeight + searchBarMargin * 2);
assertThat(actualPaddingTop).isEqualTo(searchBarHeight + searchBarMargin * 2);
}
@Test

View File

@@ -16,11 +16,13 @@
package com.android.settings.homepage.contextualcards.slices;
import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_DEFERRED_SETUP;
import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.app.Activity;
@@ -160,6 +162,15 @@ public class SliceContextualCardRendererTest {
assertThat(swipeBg.getVisibility()).isEqualTo(View.GONE);
}
@Test
public void bindView_deferredSetupCard_shouldNotCrash() {
final RecyclerView.ViewHolder viewHolder = getDeferredSetupViewHolder();
final ContextualCard card = buildContextualCard(TEST_SLICE_URI);
mRenderer.mSliceLiveDataMap.put(TEST_SLICE_URI, mSliceLiveData);
mRenderer.bindView(viewHolder, card);
}
@Test
public void viewClick_keepCard_shouldShowSlice() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
@@ -246,6 +257,18 @@ public class SliceContextualCardRendererTest {
return mRenderer.createViewHolder(view, VIEW_TYPE_FULL_WIDTH);
}
private RecyclerView.ViewHolder getDeferredSetupViewHolder() {
final RecyclerView recyclerView = new RecyclerView(mActivity);
recyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
final View view = LayoutInflater.from(mActivity)
.inflate(VIEW_TYPE_DEFERRED_SETUP, recyclerView, false);
final RecyclerView.ViewHolder viewHolder = spy(
new SliceDeferredSetupCardRendererHelper.DeferredSetupCardViewHolder(view));
doReturn(VIEW_TYPE_DEFERRED_SETUP).when(viewHolder).getItemViewType();
return viewHolder;
}
private ContextualCard buildContextualCard(Uri sliceUri) {
return new ContextualCard.Builder()
.setName("test_name")

View File

@@ -0,0 +1,116 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.settings.network;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Handler;
import com.android.settings.network.telephony.DataConnectivityListener;
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 DataConnectivityListenerTest {
@Mock
private DataConnectivityListener.Client mClient;
@Mock
private ConnectivityManager mConnectivityManager;
@Mock
private Network mActiveNetwork;
private Context mContext;
private DataConnectivityListener mListener;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
when(mConnectivityManager.getActiveNetwork()).thenReturn(mActiveNetwork);
mListener = new DataConnectivityListener(mContext, mClient);
}
@Test
public void noStart_doesNotRegister() {
verify(mConnectivityManager, never()).registerNetworkCallback(any(NetworkRequest.class),
any(ConnectivityManager.NetworkCallback.class), any(Handler.class));
}
@Test
public void start_doesRegister() {
mListener.start();
verify(mConnectivityManager).registerNetworkCallback(any(NetworkRequest.class),
eq(mListener), any(Handler.class));
}
@Test
public void onCapabilitiesChanged_notActiveNetwork_noCallback() {
Network changedNetwork = mock(Network.class);
mListener.onCapabilitiesChanged(changedNetwork, mock(NetworkCapabilities.class));
verify(mClient, never()).onDataConnectivityChange();
}
@Test
public void onCapabilitiesChanged_activeNetwork_onDataConnectivityChangeFires() {
mListener.onCapabilitiesChanged(mActiveNetwork, mock(NetworkCapabilities.class));
verify(mClient).onDataConnectivityChange();
}
@Test
public void onLosing_notActiveNetwork_onDataConnectivityChangeFires() {
Network changedNetwork = mock(Network.class);
mListener.onLosing(changedNetwork, 500);
verify(mClient).onDataConnectivityChange();
}
@Test
public void onLosing_activeNetwork_onDataConnectivityChangeFires() {
mListener.onLosing(mActiveNetwork, 500);
verify(mClient).onDataConnectivityChange();
}
@Test
public void onLost_notActiveNetwork_onDataConnectivityChangeFires() {
Network changedNetwork = mock(Network.class);
mListener.onLost(changedNetwork);
verify(mClient).onDataConnectivityChange();
}
@Test
public void onLost_activeNetwork_onDataConnectivityChangeFires() {
mListener.onLost(mActiveNetwork);
verify(mClient).onDataConnectivityChange();
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.settings.network;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.net.Uri;
import android.provider.Settings;
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 MobileDataEnabledListenerTest {
private static final int SUB_ID_ONE = 111;
private static final int SUB_ID_TWO = 222;
@Mock
private MobileDataEnabledListener.Client mClient;
private Context mContext;
private MobileDataEnabledListener mListener;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mListener = new MobileDataEnabledListener(mContext, mClient);
}
@Test
public void onMobileDataEnabledChange_firesCorrectly() {
mListener.start(SUB_ID_ONE);
final Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + SUB_ID_ONE);
mContext.getContentResolver().notifyChange(uri, null);
verify(mClient).onMobileDataEnabledChange();
}
@Test
public void onMobileDataEnabledChange_doesNotFireAfterStop() {
mListener.start(SUB_ID_ONE);
mListener.stop();
final Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + SUB_ID_ONE);
mContext.getContentResolver().notifyChange(uri, null);
verify(mClient, never()).onMobileDataEnabledChange();
}
@Test
public void onMobileDataEnabledChange_changedToDifferentId_firesCorrectly() {
mListener.start(SUB_ID_ONE);
mListener.stop();
mListener.start(SUB_ID_TWO);
final Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + SUB_ID_TWO);
mContext.getContentResolver().notifyChange(uri, null);
verify(mClient).onMobileDataEnabledChange();
}
}

View File

@@ -33,6 +33,9 @@ import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -74,7 +77,13 @@ public class SubscriptionsPreferenceControllerTest {
@Mock
private SubscriptionManager mSubscriptionManager;
@Mock
private ConnectivityManager mConnectivityManager;
@Mock
private TelephonyManager mTelephonyManager;
@Mock
private Network mActiveNetwork;
@Mock
private NetworkCapabilities mCapabilities;
private Context mContext;
private LifecycleOwner mLifecycleOwner;
@@ -90,7 +99,10 @@ public class SubscriptionsPreferenceControllerTest {
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
when(mConnectivityManager.getActiveNetwork()).thenReturn(mActiveNetwork);
when(mConnectivityManager.getNetworkCapabilities(mActiveNetwork)).thenReturn(mCapabilities);
when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
when(mScreen.findPreference(eq(KEY))).thenReturn(mPreferenceCategory);
when(mPreferenceCategory.getContext()).thenReturn(mContext);
@@ -308,7 +320,8 @@ public class SubscriptionsPreferenceControllerTest {
ShadowSubscriptionManager.setDefaultDataSubscriptionId(11);
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(11);
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(11);
when(mTelephonyManager.getDataState()).thenReturn(TelephonyManager.DATA_CONNECTED);
when(mTelephonyManager.isDataEnabled()).thenReturn(true);
when(mCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
assertThat(mController.getSummary(11)).isEqualTo(
mContext.getString(R.string.default_for_calls_and_sms) + System.lineSeparator()
@@ -318,6 +331,27 @@ public class SubscriptionsPreferenceControllerTest {
mContext.getString(R.string.subscription_available));
}
@Test
public void getSummary_twoSubsOneDefaultForEverythingDataNotActive() {
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
when(sub1.getSubscriptionId()).thenReturn(11);
when(sub2.getSubscriptionId()).thenReturn(22);
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
ShadowSubscriptionManager.setDefaultDataSubscriptionId(11);
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(11);
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(11);
when(mTelephonyManager.isDataEnabled()).thenReturn(true);
assertThat(mController.getSummary(11)).isEqualTo(
mContext.getString(R.string.default_for_calls_and_sms) + System.lineSeparator()
+ mContext.getString(R.string.default_for_mobile_data));
assertThat(mController.getSummary(22)).isEqualTo(
mContext.getString(R.string.subscription_available));
}
@Test
public void getSummary_twoSubsOneDefaultForEverythingDataDisabled() {
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
@@ -329,7 +363,6 @@ public class SubscriptionsPreferenceControllerTest {
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(11);
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(11);
ShadowSubscriptionManager.setDefaultDataSubscriptionId(11);
when(mTelephonyManager.getDataState()).thenReturn(TelephonyManager.DATA_DISCONNECTED);
when(mTelephonyManager.isDataEnabled()).thenReturn(false);
assertThat(mController.getSummary(11)).isEqualTo(
@@ -351,7 +384,6 @@ public class SubscriptionsPreferenceControllerTest {
ShadowSubscriptionManager.setDefaultDataSubscriptionId(11);
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(22);
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(11);
when(mTelephonyManager.getDataState()).thenReturn(TelephonyManager.DATA_DISCONNECTED);
when(mTelephonyManager.isDataEnabled()).thenReturn(true);
assertThat(mController.getSummary(11)).isEqualTo(

View File

@@ -18,9 +18,12 @@ package com.android.settings.network.telephony;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.PersistableBundle;
@@ -76,7 +79,7 @@ public class RoamingPreferenceControllerTest {
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
doReturn(mFragmentTransaction).when(mFragmentManager).beginTransaction();
mPreference = new RestrictedSwitchPreference(mContext);
mPreference = spy(new RestrictedSwitchPreference(mContext));
mController = new RoamingPreferenceController(mContext, "roaming");
mController.init(mFragmentManager, SUB_ID);
mPreference.setKey(mController.getPreferenceKey());
@@ -140,4 +143,22 @@ public class RoamingPreferenceControllerTest {
assertThat(mPreference.isEnabled()).isTrue();
assertThat(mPreference.isChecked()).isTrue();
}
@Test
public void updateState_isNotDisabledByAdmin_shouldInvokeSetEnabled() {
when(mPreference.isDisabledByAdmin()).thenReturn(false);
mController.updateState(mPreference);
verify(mPreference).setEnabled(anyBoolean());
}
@Test
public void updateState_isDisabledByAdmin_shouldNotInvokeSetEnabled() {
when(mPreference.isDisabledByAdmin()).thenReturn(true);
mController.updateState(mPreference);
verify(mPreference, never()).setEnabled(anyBoolean());
}
}