Snap for 4557233 from aaf307e71d to pi-release
Change-Id: I09f1f870a5e8eb4d49d5385d931689a2ffb7babb
This commit is contained in:
@@ -476,7 +476,7 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<service android:name=".TetherService"
|
||||
<service android:name=".wifi.tether.TetherService"
|
||||
android:exported="true"
|
||||
android:permission="android.permission.TETHER_PRIVILEGED" />
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingEnd="@dimen/reset_checkbox_padding_end"
|
||||
android:focusable="false"
|
||||
android:clickable="false"
|
||||
android:duplicateParentState="true" />
|
||||
@@ -104,14 +104,14 @@
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="12dp"
|
||||
android:textSize="18sp"
|
||||
android:paddingTop="@dimen/reset_checkbox_title_padding_top"
|
||||
android:textSize="@dimen/reset_checkbox_title_text_size"
|
||||
android:text="@string/erase_external_storage" />
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="4sp"
|
||||
android:textSize="14sp"
|
||||
android:paddingTop="@dimen/reset_checkbox_summary_padding_top"
|
||||
android:textSize="@dimen/reset_checkbox_summary_text_size"
|
||||
android:text="@string/erase_external_storage_description" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
51
res/layout/reset_esim_checkbox.xml
Normal file
51
res/layout/reset_esim_checkbox.xml
Normal file
@@ -0,0 +1,51 @@
|
||||
<?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.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
android:visibility="gone">
|
||||
|
||||
<CheckBox android:id="@+id/erase_esim"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingEnd="@dimen/reset_checkbox_padding_end"
|
||||
android:focusable="false"
|
||||
android:clickable="false"
|
||||
android:duplicateParentState="true" />
|
||||
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView android:id="@+id/erase_esim_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/reset_checkbox_title_padding_top"
|
||||
android:textSize="@dimen/reset_checkbox_title_text_size" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/reset_checkbox_summary_padding_top"
|
||||
android:textSize="@dimen/reset_checkbox_summary_text_size"
|
||||
android:text="@string/reset_esim_desc" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -14,7 +14,8 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
@@ -27,7 +28,8 @@
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
@@ -38,6 +40,11 @@
|
||||
android:textDirection="locale"
|
||||
android:text="@string/reset_network_desc" />
|
||||
|
||||
<include layout="@layout/reset_esim_checkbox"
|
||||
android:id="@+id/erase_esim_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
@@ -57,8 +57,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="20dp"
|
||||
android:paddingBottom="16dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:scrollbars="none"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
android:layout_width="328dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardUseCompatPadding="true"
|
||||
app:cardElevation="2dp">
|
||||
app:cardElevation="2dp"
|
||||
app:cardCornerRadius="@dimen/suggestion_card_corner_radius">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -38,7 +39,7 @@
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="@dimen/dashboard_tile_image_size"
|
||||
android:layout_height="@dimen/dashboard_tile_image_size"
|
||||
android:layout_centerHorizontal = "true"
|
||||
style="@style/SuggestionCardIcon"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
@@ -55,21 +56,23 @@
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
style="@style/SuggestionCardText"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:singleLine="true"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:textAppearance="@style/TextAppearance.TileTitle"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal" />
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
style="@style/SuggestionCardText"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:textAppearance="@style/TextAppearance.SuggestionSummary" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -21,14 +21,14 @@
|
||||
android:layout_width="328dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardUseCompatPadding="true"
|
||||
app:cardElevation="2dp">
|
||||
app:cardElevation="2dp"
|
||||
app:cardCornerRadius="@dimen/suggestion_card_corner_radius">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="112dp"
|
||||
android:orientation="vertical"
|
||||
android:background="@android:color/white">
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -39,7 +39,7 @@
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="@dimen/dashboard_tile_image_size"
|
||||
android:layout_height="@dimen/dashboard_tile_image_size"
|
||||
android:layout_centerHorizontal = "true"
|
||||
style="@style/SuggestionCardIcon"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
@@ -56,9 +56,11 @@
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
style="@style/SuggestionCardText"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.TileTitle"
|
||||
android:ellipsize="marquee"
|
||||
@@ -66,9 +68,11 @@
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
style="@style/SuggestionCardText"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:textAppearance="@style/TextAppearance.SuggestionSummary" />
|
||||
|
||||
<Button
|
||||
|
||||
@@ -120,6 +120,24 @@
|
||||
<!-- Whether vibrate_input_devices should be shown or not. -->
|
||||
<bool name="config_show_vibrate_input_devices">true</bool>
|
||||
|
||||
<!-- Whether manage_device_admin should be shown or not. -->
|
||||
<bool name="config_show_manage_device_admin">true</bool>
|
||||
|
||||
<!-- Whether unlock_set_or_change should be shown or not. -->
|
||||
<bool name="config_show_unlock_set_or_change">true</bool>
|
||||
|
||||
<!-- Whether screen_pinning_settings should be shown or not. -->
|
||||
<bool name="config_show_screen_pinning_settings">true</bool>
|
||||
|
||||
<!-- Whether manage_trust_agents should be shown or not. -->
|
||||
<bool name="config_show_manage_trust_agents">true</bool>
|
||||
|
||||
<!-- Whether show_password should be shown or not. -->
|
||||
<bool name="config_show_show_password">true</bool>
|
||||
|
||||
<!-- Whether trust_agent_click_intent should be shown or not. -->
|
||||
<bool name="config_show_trust_agent_click_intent">true</bool>
|
||||
|
||||
<!-- Whether wallpaper attribution should be shown or not. -->
|
||||
<bool name="config_show_wallpaper_attribution">true</bool>
|
||||
|
||||
|
||||
@@ -300,11 +300,22 @@
|
||||
<dimen name="suggestion_condition_header_padding_collapsed">10dp</dimen>
|
||||
<dimen name="suggestion_condition_header_padding_expanded">5dp</dimen>
|
||||
|
||||
<!-- Suggestion cards-->
|
||||
<!-- Suggestion cards size and padding -->
|
||||
<dimen name="suggestion_card_width_one_card">328dp</dimen>
|
||||
<dimen name="suggestion_card_width_two_cards">158dp</dimen>
|
||||
<dimen name="suggestion_card_width_multiple_cards">152dp</dimen>
|
||||
<dimen name="suggestion_card_margin_end">12dp</dimen>
|
||||
<dimen name="suggestion_card_outer_margin">16dp</dimen>
|
||||
<dimen name="suggestion_card_inner_margin">12dp</dimen>
|
||||
<dimen name="suggestion_card_padding_bottom_one_card">16dp</dimen>
|
||||
<dimen name="suggestion_card_corner_radius">2dp</dimen>
|
||||
<dimen name="suggestion_card_title_padding_bottom_one_card">6dp</dimen>
|
||||
<dimen name="suggestion_card_title_padding_bottom_multiple_cards">8dp</dimen>
|
||||
|
||||
<!-- Padding for the reset screens -->
|
||||
<dimen name="reset_checkbox_padding_end">8dp</dimen>
|
||||
<dimen name="reset_checkbox_title_padding_top">12dp</dimen>
|
||||
<dimen name="reset_checkbox_summary_padding_top">4dp</dimen>
|
||||
<dimen name="reset_checkbox_title_text_size">18sp</dimen>
|
||||
<dimen name="reset_checkbox_summary_text_size">14sp</dimen>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -3213,6 +3213,10 @@
|
||||
<string name="reset_network_title">Reset Wi-Fi, mobile & Bluetooth</string>
|
||||
<!-- SD card & phone storage settings screen, message on screen after user selects Reset network settings [CHAR LIMIT=NONE] -->
|
||||
<string name="reset_network_desc">This will reset all network settings, including:\n\n<li>Wi\u2011Fi</li>\n<li>Mobile data</li>\n<li>Bluetooth</li>"</string>
|
||||
<!-- SD card & phone storage settings screen, title for the checkbox to let user decide whether erase eSIM data together [CHAR LIMIT=NONE] -->
|
||||
<string name="reset_esim_title">Also reset eSIMs</string>
|
||||
<!-- SD card & phone storage settings screen, message for the checkbox to let user decide whether erase eSIM data together [CHAR LIMIT=NONE] -->
|
||||
<string name="reset_esim_desc">Erase all eSIMs on the phone. You\u2019ll have to contract your carrier to redownload your eSIMs. This will not cancel your mobile service plan.</string>
|
||||
<!-- SD card & phone storage settings screen, button on screen after user selects Reset network settings -->
|
||||
<string name="reset_network_button_text">Reset settings</string>
|
||||
<!-- SD card & phone storage settings screen, message on screen after user selects Reset settings button -->
|
||||
@@ -3225,6 +3229,10 @@
|
||||
<string name="network_reset_not_available">Network reset is not available for this user</string>
|
||||
<!-- Reset settings complete toast text [CHAR LIMIT=75] -->
|
||||
<string name="reset_network_complete_toast">Network settings have been reset</string>
|
||||
<!-- Title of the error message shown when error happens during erase eSIM data [CHAR LIMIT=NONE] -->
|
||||
<string name="reset_esim_error_title">Cant\u2019t reset eSIMs</string>
|
||||
<!-- Message of the error message shown when error happens during erase eSIM data [CHAR LIMIT=NONE] -->
|
||||
<string name="reset_esim_error_msg">The eSIMs can\u2019tt be reset due to an error.</string>
|
||||
|
||||
<!-- Master Clear -->
|
||||
<!-- Button title to factory data reset the entire device -->
|
||||
@@ -6870,6 +6878,9 @@
|
||||
<!-- Do not disturb: Summary for the zen mode automation option Suggestion. [CHAR LIMIT=NONE] -->
|
||||
<string name="zen_mode_automation_suggestion_summary">Limit sounds & vibrations at certain times</string>
|
||||
|
||||
<!-- Do not disturb: Switch toggle to toggle whether to use an automatic dnd rule or not [CHAR LIMIT=40] -->
|
||||
<string name="zen_mode_use_automatic_rule">Use rule</string>
|
||||
|
||||
<!-- Do not disturb: Zen mode option: Important interruptions [CHAR LIMIT=60] -->
|
||||
<string name="zen_mode_option_important_interruptions">Priority only</string>
|
||||
|
||||
@@ -8677,6 +8688,9 @@
|
||||
<!-- Notification log debug tool: the word 'none' -->
|
||||
<string name="notification_log_details_ranking_none">Ranking object doesn\'t contain this key.</string>
|
||||
|
||||
<!-- [CHAR_LIMIT=NONE] Developer Settings: Title of the setting which turns on emulation of a display cutout. -->
|
||||
<string name="display_cutout_emulation">Emulate a display with a cutout</string>
|
||||
|
||||
<!-- [CHAR_LIMIT=60] Label for special access screen -->
|
||||
<string name="special_access">Special app access</string>
|
||||
|
||||
@@ -8743,7 +8757,7 @@
|
||||
<string name="window_trace_quick_settings_title">Window Trace</string>
|
||||
|
||||
<!-- [CHAR LIMIT=25] Title of developer tile to toggle layer trace -->
|
||||
<string name="layer_trace_quick_settings_title">Layer Trace</string>
|
||||
<string name="layer_trace_quick_settings_title">Surface Trace</string>
|
||||
|
||||
<!-- [CHAR LIMIT=60] Title of work profile setting page -->
|
||||
<string name="managed_profile_settings_title">Work profile settings</string>
|
||||
@@ -9185,9 +9199,21 @@
|
||||
<!-- UI debug setting: preference summary - describes the behavior of forcing full raw GNSS satellite measurements [CHAR LIMIT=NONE] -->
|
||||
<string name="enable_gnss_raw_meas_full_tracking_summary">Track all GNSS constellations and frequencies with no duty cycling</string>
|
||||
|
||||
<!-- Title for Storage Access settings -->
|
||||
<string name="storage_access">Storage access</string>
|
||||
<!-- Keywords for Storage Access settings -->
|
||||
<string name="keywords_storage_access">storage access scoped directory</string>
|
||||
<!-- UI debug setting: preference title - show all crash dialogs [CHAR LIMIT=60] -->
|
||||
<string name="show_first_crash_dialog">Always show crash dialog</string>
|
||||
<!-- UI debug setting: preference summary - describes the behavior of showing a dialog every time an app crashes [CHAR LIMIT=NONE] -->
|
||||
<string name="show_first_crash_dialog_summary">Show dialog every time an app crashes</string>
|
||||
|
||||
<!-- Title for Directory Access settings -->
|
||||
<string name="directory_access">Directory access</string>
|
||||
<!-- Keywords for Directory Access settings -->
|
||||
<string name="keywords_directory_access">directory access</string>
|
||||
|
||||
<!-- Account type associated with the backup account. Empty for AOSP. [DO NOT TRANSLATE] -->
|
||||
<string name="account_type"></string>
|
||||
<!-- Package to target for Account credential confirmation. This will allow users to
|
||||
remind/rediscover their backup account password prior to a reset. Empty for AOSP.
|
||||
[DO NOT TRANSLATE] -->
|
||||
<string name="account_confirmation_package"></string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -323,6 +323,15 @@
|
||||
<item name="android:textColor">?android:attr/colorAccent</item>
|
||||
</style>
|
||||
|
||||
<style name="SuggestionCardText">
|
||||
<item name="android:textAlignment">viewStart</item>
|
||||
</style>
|
||||
|
||||
<style name="SuggestionCardIcon">
|
||||
<item name="android:layout_centerHorizontal">false</item>
|
||||
<item name="android:layout_alignParentStart">true</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.SuggestionTitle"
|
||||
parent="@android:style/TextAppearance.Material.Subhead">
|
||||
<item name="android:fontFamily">sans-serif-medium</item>
|
||||
|
||||
@@ -202,16 +202,6 @@
|
||||
android:title="@string/wifi_verbose_logging"
|
||||
android:summary="@string/wifi_verbose_logging_summary"/>
|
||||
|
||||
<SwitchPreference
|
||||
android:key="wifi_aggressive_handover"
|
||||
android:title="@string/wifi_aggressive_handover"
|
||||
android:summary="@string/wifi_aggressive_handover_summary"/>
|
||||
|
||||
<SwitchPreference
|
||||
android:key="wifi_allow_scan_with_traffic"
|
||||
android:title="@string/wifi_allow_scan_with_traffic"
|
||||
android:summary="@string/wifi_allow_scan_with_traffic_summary"/>
|
||||
|
||||
<SwitchPreference
|
||||
android:key="mobile_data_always_on"
|
||||
android:title="@string/mobile_data_always_on"
|
||||
@@ -356,6 +346,10 @@
|
||||
android:key="density"
|
||||
android:title="@string/developer_smallest_width" />
|
||||
|
||||
<SwitchPreference
|
||||
android:key="display_cutout_emulation"
|
||||
android:title="@string/display_cutout_emulation" />
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:key="debug_hw_drawing_category"
|
||||
@@ -459,6 +453,10 @@
|
||||
android:fragment="com.android.settings.applications.appops.BackgroundCheckSummary"
|
||||
android:title="@string/background_check_pref" />
|
||||
|
||||
<SwitchPreference
|
||||
android:key="show_first_crash_dialog"
|
||||
android:title="@string/show_first_crash_dialog"
|
||||
android:summary="@string/show_first_crash_dialog_summary"/>
|
||||
|
||||
<SwitchPreference
|
||||
android:key="show_all_anrs"
|
||||
|
||||
24
res/xml/restricted_apps_detail.xml
Normal file
24
res/xml/restricted_apps_detail.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:title="@string/restricted_app_title">
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="restrict_app_list"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -158,14 +158,4 @@
|
||||
android:summary="@string/summary_placeholder"
|
||||
android:fragment="com.android.settings.security.ScreenPinningSettings" />
|
||||
|
||||
<Preference
|
||||
android:order="90"
|
||||
android:key="security_misc_usage_access"
|
||||
android:title="@string/usage_access_title"
|
||||
android:fragment="com.android.settings.applications.manageapplications.ManageApplications">
|
||||
<extra
|
||||
android:name="classname"
|
||||
android:value="com.android.settings.Settings$UsageAccessSettingsActivity" />
|
||||
</Preference>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -113,13 +113,13 @@
|
||||
|
||||
<!-- TODO(b/63720392): add when ready
|
||||
<Preference
|
||||
android:key="special_app_storage_access"
|
||||
android:title="@string/storage_access"
|
||||
android:key="special_app_directory_access"
|
||||
android:title="@string/directory_access"
|
||||
android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
|
||||
settings:keywords="@string/keywords_storage_access">
|
||||
settings:keywords="@string/keywords_directory_access">
|
||||
<extra
|
||||
android:name="classname"
|
||||
android:value="com.android.settings.Settings$StorageAccessSettingsActivity" />
|
||||
android:value="com.android.settings.Settings$DirectoryeAccessSettingsActivity" />
|
||||
</Preference>
|
||||
-->
|
||||
|
||||
|
||||
@@ -28,12 +28,6 @@
|
||||
android:key="zen_automatic_rule_switch"
|
||||
android:layout="@layout/styled_switch_bar" />
|
||||
|
||||
<!-- Rule name -->
|
||||
<Preference
|
||||
android:key="rule_name"
|
||||
android:title="@string/zen_mode_rule_name"
|
||||
android:persistent="false" />
|
||||
|
||||
<!-- During events for -->
|
||||
<DropDownPreference
|
||||
android:key="calendar"
|
||||
|
||||
@@ -28,12 +28,6 @@
|
||||
android:key="zen_automatic_rule_switch"
|
||||
android:layout="@layout/styled_switch_bar" />
|
||||
|
||||
<!-- Rule name -->
|
||||
<Preference
|
||||
android:key="rule_name"
|
||||
android:title="@string/zen_mode_rule_name"
|
||||
android:persistent="false" />
|
||||
|
||||
<!-- Days -->
|
||||
<Preference
|
||||
android:key="days"
|
||||
|
||||
@@ -30,8 +30,8 @@ import android.support.v7.preference.Preference;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.telephony.PhoneStateIntentReceiver;
|
||||
import com.android.internal.telephony.TelephonyProperties;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.WirelessUtils;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
public class AirplaneModeEnabler implements Preference.OnPreferenceChangeListener {
|
||||
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import static android.provider.Telephony.Carriers.FILTERED_URI;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.provider.Telephony;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceViewHolder;
|
||||
import android.telephony.SubscriptionManager;
|
||||
@@ -118,7 +119,7 @@ public class ApnPreference extends Preference implements
|
||||
Context context = getContext();
|
||||
if (context != null) {
|
||||
int pos = Integer.parseInt(getKey());
|
||||
Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos);
|
||||
Uri url = ContentUris.withAppendedId(FILTERED_URI, pos);
|
||||
Intent editIntent = new Intent(Intent.ACTION_EDIT, url);
|
||||
editIntent.putExtra(ApnSettings.SUB_ID, mSubId);
|
||||
context.startActivity(editIntent);
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
|
||||
import static android.provider.Telephony.Carriers.FILTERED_URI;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
@@ -39,7 +42,6 @@ import android.os.UserManager;
|
||||
import android.provider.Telephony;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceGroup;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
@@ -50,7 +52,6 @@ import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
@@ -246,6 +247,17 @@ public class ApnSettings extends RestrictedSettingsFragment implements
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isDpcApnEnforced() {
|
||||
try (Cursor enforceCursor = getContentResolver().query(ENFORCE_MANAGED_URI,
|
||||
null, null, null, null)) {
|
||||
if (enforceCursor == null || enforceCursor.getCount() != 1) {
|
||||
return false;
|
||||
}
|
||||
enforceCursor.moveToFirst();
|
||||
return enforceCursor.getInt(0) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void fillList() {
|
||||
final TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
|
||||
final int subId = mSubscriptionInfo != null ? mSubscriptionInfo.getSubscriptionId()
|
||||
@@ -259,9 +271,9 @@ public class ApnSettings extends RestrictedSettingsFragment implements
|
||||
where.append(" AND NOT (type='ims')");
|
||||
}
|
||||
|
||||
Cursor cursor = getContentResolver().query(Telephony.Carriers.CONTENT_URI, new String[] {
|
||||
"_id", "name", "apn", "type", "mvno_type", "mvno_match_data"}, where.toString(),
|
||||
null, Telephony.Carriers.DEFAULT_SORT_ORDER);
|
||||
Cursor cursor = getContentResolver().query(FILTERED_URI,
|
||||
new String[] {"_id", "name", "apn", "type", "mvno_type", "mvno_match_data"},
|
||||
where.toString(), null, Telephony.Carriers.DEFAULT_SORT_ORDER);
|
||||
|
||||
if (cursor != null) {
|
||||
IccRecords r = null;
|
||||
@@ -343,15 +355,14 @@ public class ApnSettings extends RestrictedSettingsFragment implements
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
if (!mUnavailable) {
|
||||
if (!mUnavailable && !isDpcApnEnforced()) {
|
||||
if (mAllowAddingApns) {
|
||||
menu.add(0, MENU_NEW, 0,
|
||||
getResources().getString(R.string.menu_new))
|
||||
.setIcon(R.drawable.ic_menu_add_white)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
}
|
||||
menu.add(0, MENU_RESTORE, 0,
|
||||
getResources().getString(R.string.menu_restore))
|
||||
menu.add(0, MENU_RESTORE, 0, getResources().getString(R.string.menu_restore))
|
||||
.setIcon(android.R.drawable.ic_menu_upload);
|
||||
}
|
||||
|
||||
@@ -387,7 +398,7 @@ public class ApnSettings extends RestrictedSettingsFragment implements
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(Preference preference) {
|
||||
int pos = Integer.parseInt(preference.getKey());
|
||||
Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos);
|
||||
Uri url = ContentUris.withAppendedId(FILTERED_URI, pos);
|
||||
startActivity(new Intent(Intent.ACTION_EDIT, url));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -49,8 +49,9 @@ import android.widget.Switch;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.core.instrumentation.Instrumentable;
|
||||
import com.android.settings.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.Instrumentable;
|
||||
import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
@@ -63,8 +64,7 @@ import java.util.List;
|
||||
public class DeviceAdminSettings extends ListFragment implements Instrumentable {
|
||||
static final String TAG = "DeviceAdminSettings";
|
||||
|
||||
private final VisibilityLoggerMixin mVisibilityLoggerMixin =
|
||||
new VisibilityLoggerMixin(getMetricsCategory());
|
||||
private VisibilityLoggerMixin mVisibilityLoggerMixin;
|
||||
private DevicePolicyManager mDPM;
|
||||
private UserManager mUm;
|
||||
|
||||
@@ -85,12 +85,6 @@ public class DeviceAdminSettings extends ListFragment implements Instrumentable
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
mVisibilityLoggerMixin.onAttach(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal collection of device admin info objects for all profiles associated with the current
|
||||
* user.
|
||||
@@ -121,6 +115,8 @@ public class DeviceAdminSettings extends ListFragment implements Instrumentable
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
mVisibilityLoggerMixin = new VisibilityLoggerMixin(getMetricsCategory(),
|
||||
FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -39,6 +40,7 @@ import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.telephony.euicc.EuiccManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@@ -74,6 +76,7 @@ public class MasterClear extends InstrumentedPreferenceFragment {
|
||||
private static final String TAG = "MasterClear";
|
||||
|
||||
private static final int KEYGUARD_REQUEST = 55;
|
||||
private static final int CREDENTIAL_CONFIRM_REQUEST = 56;
|
||||
|
||||
static final String ERASE_EXTERNAL_EXTRA = "erase_sd";
|
||||
static final String ERASE_ESIMS_EXTRA = "erase_esim";
|
||||
@@ -114,7 +117,7 @@ public class MasterClear extends InstrumentedPreferenceFragment {
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (requestCode != KEYGUARD_REQUEST) {
|
||||
if (requestCode != KEYGUARD_REQUEST || requestCode != CREDENTIAL_CONFIRM_REQUEST) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -138,6 +141,33 @@ public class MasterClear extends InstrumentedPreferenceFragment {
|
||||
args, R.string.master_clear_confirm_title, null, null, 0);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean tryShowAccountConfirmation() {
|
||||
final Context context = getActivity();
|
||||
final String accountType = context.getString(R.string.account_type);
|
||||
final String packageName = context.getString(R.string.account_confirmation_package);
|
||||
if (TextUtils.isEmpty(accountType) || TextUtils.isEmpty(packageName)) {
|
||||
return false;
|
||||
}
|
||||
final AccountManager am = AccountManager.get(context);
|
||||
Account[] accounts = am.getAccountsByType(accountType);
|
||||
if (accounts != null && accounts.length > 0) {
|
||||
final Intent requestAccountConfirmation = new Intent()
|
||||
.setPackage(packageName)
|
||||
.setAction("android.accounts.action.PRE_FACTORY_RESET");
|
||||
// Check to make sure that the intent is supported.
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
final List<ResolveInfo> resolutions =
|
||||
pm.queryIntentActivities(requestAccountConfirmation, 0);
|
||||
if (resolutions != null && resolutions.size() > 0) {
|
||||
getActivity().startActivityForResult(
|
||||
requestAccountConfirmation, CREDENTIAL_CONFIRM_REQUEST);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user clicks to begin the reset sequence, we next require a
|
||||
* keyguard confirmation if the user has currently enabled one. If there
|
||||
@@ -158,7 +188,10 @@ public class MasterClear extends InstrumentedPreferenceFragment {
|
||||
.setAction(Intent.ACTION_FACTORY_RESET);
|
||||
context.startActivity(requestFactoryReset);
|
||||
}
|
||||
} else if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tryShowAccountConfirmation() && !runKeyguardConfirmation(KEYGUARD_REQUEST)) {
|
||||
showFinalConfirmation();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,20 +18,28 @@ package com.android.settings;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.Global;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.euicc.EuiccManager;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.telephony.PhoneConstants;
|
||||
@@ -64,6 +72,8 @@ public class ResetNetwork extends InstrumentedPreferenceFragment {
|
||||
private View mContentView;
|
||||
private Spinner mSubscriptionSpinner;
|
||||
private Button mInitiateButton;
|
||||
private View mEsimContainer;
|
||||
private CheckBox mEsimCheckbox;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -107,6 +117,7 @@ public class ResetNetwork extends InstrumentedPreferenceFragment {
|
||||
SubscriptionInfo subscription = mSubscriptions.get(selectedIndex);
|
||||
args.putInt(PhoneConstants.SUBSCRIPTION_KEY, subscription.getSubscriptionId());
|
||||
}
|
||||
args.putBoolean(MasterClear.ERASE_ESIMS_EXTRA, mEsimCheckbox.isChecked());
|
||||
((SettingsActivity) getActivity()).startPreferencePanel(
|
||||
this, ResetNetworkConfirm.class.getName(),
|
||||
args, R.string.reset_network_confirm_title, null, null, 0);
|
||||
@@ -141,6 +152,8 @@ public class ResetNetwork extends InstrumentedPreferenceFragment {
|
||||
*/
|
||||
private void establishInitialState() {
|
||||
mSubscriptionSpinner = (Spinner) mContentView.findViewById(R.id.reset_network_subscription);
|
||||
mEsimContainer = mContentView.findViewById(R.id.erase_esim_container);
|
||||
mEsimCheckbox = mContentView.findViewById(R.id.erase_esim);
|
||||
|
||||
mSubscriptions = SubscriptionManager.from(getActivity()).getActiveSubscriptionInfoList();
|
||||
if (mSubscriptions != null && mSubscriptions.size() > 0) {
|
||||
@@ -192,6 +205,30 @@ public class ResetNetwork extends InstrumentedPreferenceFragment {
|
||||
}
|
||||
mInitiateButton = (Button) mContentView.findViewById(R.id.initiate_reset_network);
|
||||
mInitiateButton.setOnClickListener(mInitiateListener);
|
||||
if (showEuiccSettings(getContext())) {
|
||||
mEsimContainer.setVisibility(View.VISIBLE);
|
||||
TextView title = mContentView.findViewById(R.id.erase_esim_title);
|
||||
title.setText(R.string.reset_esim_title);
|
||||
mEsimContainer.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mEsimCheckbox.toggle();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mEsimCheckbox.setChecked(false /* checked */);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean showEuiccSettings(Context context) {
|
||||
EuiccManager euiccManager =
|
||||
(EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
|
||||
if (!euiccManager.isEnabled()) {
|
||||
return false;
|
||||
}
|
||||
ContentResolver resolver = context.getContentResolver();
|
||||
return Settings.Global.getInt(resolver, Global.EUICC_PROVISIONED, 0) != 0
|
||||
|| Settings.Global.getInt(resolver, Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.settings;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothManager;
|
||||
import android.content.ContentResolver;
|
||||
@@ -24,9 +25,12 @@ import android.net.ConnectivityManager;
|
||||
import android.net.NetworkPolicyManager;
|
||||
import android.net.Uri;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.RecoverySystem;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -39,6 +43,7 @@ import com.android.ims.ImsManager;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.telephony.PhoneConstants;
|
||||
import com.android.settings.core.InstrumentedPreferenceFragment;
|
||||
import com.android.settings.wrapper.RecoverySystemWrapper;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
|
||||
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||
@@ -57,6 +62,43 @@ public class ResetNetworkConfirm extends InstrumentedPreferenceFragment {
|
||||
|
||||
private View mContentView;
|
||||
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||
@VisibleForTesting boolean mEraseEsim;
|
||||
@VisibleForTesting EraseEsimAsyncTask mEraseEsimTask;
|
||||
@VisibleForTesting static RecoverySystemWrapper mRecoverySystem;
|
||||
|
||||
/**
|
||||
* Async task used to erase all the eSIM profiles from the phone. If error happens during
|
||||
* erasing eSIM profiles or timeout, an error msg is shown.
|
||||
*/
|
||||
private static class EraseEsimAsyncTask extends AsyncTask<Void, Void, Boolean> {
|
||||
private final Context mContext;
|
||||
private final String mPackageName;
|
||||
|
||||
EraseEsimAsyncTask(Context context, String packageName) {
|
||||
mContext = context;
|
||||
mPackageName = packageName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... params) {
|
||||
return mRecoverySystem.wipeEuiccData(
|
||||
mContext, true /* isWipeEuicc */, mPackageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean succeeded) {
|
||||
if (succeeded) {
|
||||
Toast.makeText(mContext, R.string.reset_network_complete_toast, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
} else {
|
||||
new AlertDialog.Builder(mContext)
|
||||
.setTitle(R.string.reset_esim_error_title)
|
||||
.setMessage(R.string.reset_esim_error_msg)
|
||||
.setPositiveButton(android.R.string.ok, null /* listener */)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The user has gone through the multiple confirmation, so now we go ahead
|
||||
@@ -69,7 +111,8 @@ public class ResetNetworkConfirm extends InstrumentedPreferenceFragment {
|
||||
if (Utils.isMonkeyRunning()) {
|
||||
return;
|
||||
}
|
||||
// TODO maybe show a progress dialog if this ends up taking a while
|
||||
// TODO maybe show a progress screen if this ends up taking a while and won't let user
|
||||
// go back until the tasks finished.
|
||||
Context context = getActivity();
|
||||
|
||||
ConnectivityManager connectivityManager = (ConnectivityManager)
|
||||
@@ -108,11 +151,20 @@ public class ResetNetworkConfirm extends InstrumentedPreferenceFragment {
|
||||
|
||||
ImsManager.factoryReset(context);
|
||||
restoreDefaultApn(context);
|
||||
esimFactoryReset(context, context.getPackageName());
|
||||
}
|
||||
};
|
||||
|
||||
@VisibleForTesting
|
||||
void esimFactoryReset(Context context, String packageName) {
|
||||
if (mEraseEsim) {
|
||||
mEraseEsimTask = new EraseEsimAsyncTask(context, packageName);
|
||||
mEraseEsimTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
} else {
|
||||
Toast.makeText(context, R.string.reset_network_complete_toast, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore APN settings to default.
|
||||
@@ -163,6 +215,16 @@ public class ResetNetworkConfirm extends InstrumentedPreferenceFragment {
|
||||
if (args != null) {
|
||||
mSubId = args.getInt(PhoneConstants.SUBSCRIPTION_KEY,
|
||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
||||
mEraseEsim = args.getBoolean(MasterClear.ERASE_ESIMS_EXTRA);
|
||||
}
|
||||
mRecoverySystem = new RecoverySystemWrapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (mEraseEsimTask != null) {
|
||||
mEraseEsimTask.cancel(true /* mayInterruptIfRunning */);
|
||||
mEraseEsimTask = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ public class Settings extends SettingsActivity {
|
||||
public static class PhotosStorageActivity extends SettingsActivity {
|
||||
/* empty */
|
||||
}
|
||||
public static class StorageAccessSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class DirectoryAccessSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
|
||||
public static class TopLevelSettings extends SettingsActivity { /* empty */ }
|
||||
public static class ApnSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
|
||||
@@ -56,13 +56,13 @@ import com.android.settings.Settings.WifiSettingsActivity;
|
||||
import com.android.settings.applications.manageapplications.ManageApplications;
|
||||
import com.android.settings.backup.BackupSettingsActivity;
|
||||
import com.android.settings.core.gateway.SettingsGateway;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.core.instrumentation.SharedPreferencesLogger;
|
||||
import com.android.settings.dashboard.DashboardFeatureProvider;
|
||||
import com.android.settings.dashboard.DashboardSummary;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.wfd.WifiDisplaySettings;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.instrumentation.SharedPreferencesLogger;
|
||||
import com.android.settingslib.development.DevelopmentSettingsEnabler;
|
||||
import com.android.settingslib.drawer.DashboardCategory;
|
||||
import com.android.settingslib.drawer.SettingsDrawerActivity;
|
||||
@@ -92,11 +92,6 @@ public class SettingsActivity extends SettingsDrawerActivity
|
||||
*/
|
||||
public static final String EXTRA_SHOW_FRAGMENT = ":settings:show_fragment";
|
||||
|
||||
/**
|
||||
* The metrics category constant for logging source when a setting fragment is opened.
|
||||
*/
|
||||
public static final String EXTRA_SOURCE_METRICS_CATEGORY = ":settings:source_metrics";
|
||||
|
||||
/**
|
||||
* When starting this activity and using {@link #EXTRA_SHOW_FRAGMENT},
|
||||
* this extra can also be specified to supply a Bundle of arguments to pass
|
||||
@@ -220,7 +215,8 @@ public class SettingsActivity extends SettingsDrawerActivity
|
||||
@Override
|
||||
public SharedPreferences getSharedPreferences(String name, int mode) {
|
||||
if (name.equals(getPackageName() + "_preferences")) {
|
||||
return new SharedPreferencesLogger(this, getMetricsTag());
|
||||
return new SharedPreferencesLogger(this, getMetricsTag(),
|
||||
FeatureFactory.getFactory(this).getMetricsFeatureProvider());
|
||||
}
|
||||
return super.getSharedPreferences(name, mode);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ import android.widget.Button;
|
||||
|
||||
import com.android.settings.applications.LayoutPreference;
|
||||
import com.android.settings.core.InstrumentedPreferenceFragment;
|
||||
import com.android.settings.core.instrumentation.Instrumentable;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
import com.android.settings.search.actionbar.SearchMenuController;
|
||||
import com.android.settings.support.actionbar.HelpMenuController;
|
||||
@@ -53,6 +52,7 @@ import com.android.settings.support.actionbar.HelpResourceProvider;
|
||||
import com.android.settings.widget.LoadingViewController;
|
||||
import com.android.settingslib.CustomDialogPreference;
|
||||
import com.android.settingslib.CustomEditTextPreference;
|
||||
import com.android.settingslib.core.instrumentation.Instrumentable;
|
||||
import com.android.settingslib.widget.FooterPreferenceMixin;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -110,6 +110,7 @@ import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
|
||||
import com.android.settings.wrapper.FingerprintManagerWrapper;
|
||||
import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
@@ -576,7 +577,7 @@ public final class Utils extends com.android.settingslib.Utils {
|
||||
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, titleResId);
|
||||
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE, title);
|
||||
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_AS_SHORTCUT, isShortcut);
|
||||
intent.putExtra(SettingsActivity.EXTRA_SOURCE_METRICS_CATEGORY, sourceMetricsCategory);
|
||||
intent.putExtra(VisibilityLoggerMixin.EXTRA_SOURCE_METRICS_CATEGORY, sourceMetricsCategory);
|
||||
return intent;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,12 +51,12 @@ import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.search.SearchIndexableRaw;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
import com.android.settingslib.accounts.AuthenticatorHelper;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
|
||||
@@ -34,11 +34,11 @@ import com.android.settingslib.applications.ApplicationsState.AppFilter;
|
||||
import java.util.Set;
|
||||
|
||||
// TODO(b/63720392): add unit tests
|
||||
public class AppStateStorageAccessBridge extends AppStateBaseBridge {
|
||||
public class AppStateDirectoryAccessBridge extends AppStateBaseBridge {
|
||||
|
||||
private static final String TAG = "StorageAccessBridge";
|
||||
private static final String TAG = "DirectoryAccessBridge";
|
||||
|
||||
public AppStateStorageAccessBridge(ApplicationsState appState, Callback callback) {
|
||||
public AppStateDirectoryAccessBridge(ApplicationsState appState, Callback callback) {
|
||||
super(appState, callback);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class AppStateStorageAccessBridge extends AppStateBaseBridge {
|
||||
@Override
|
||||
protected void updateExtraInfo(AppEntry app, String pkg, int uid) { }
|
||||
|
||||
public static final AppFilter FILTER_APP_HAS_STORAGE_ACCESS = new AppFilter() {
|
||||
public static final AppFilter FILTER_APP_HAS_DIRECTORY_ACCESS = new AppFilter() {
|
||||
|
||||
private Set<String> mPackages;
|
||||
|
||||
@@ -38,13 +38,13 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
|
||||
/**
|
||||
* Detailed settings for an app's storage access permissions (A.K.A Scoped Directory Access).
|
||||
* Detailed settings for an app's directory access permissions (A.K.A Scoped Directory Access).
|
||||
*/
|
||||
// TODO(b/63720392): explain its layout
|
||||
// TODO(b/63720392): add unit tests
|
||||
public class StorageAccessDetails extends AppInfoWithHeader implements OnPreferenceChangeListener,
|
||||
public class DirectoryAccessDetails extends AppInfoWithHeader implements OnPreferenceChangeListener,
|
||||
OnPreferenceClickListener {
|
||||
private static final String MY_TAG = "StorageAccessDetails";
|
||||
private static final String MY_TAG = "DirectoryAccessDetails";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -105,6 +105,6 @@ public class StorageAccessDetails extends AppInfoWithHeader implements OnPrefere
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.APPLICATIONS_USAGE_ACCESS_DETAIL;
|
||||
return MetricsEvent.APPLICATIONS_DIRECTORY_ACCESS_DETAIL;
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,7 @@ import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
|
||||
import com.android.settings.core.FeatureFlags;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.widget.AppPreference;
|
||||
import com.android.settingslib.applications.AppUtils;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.wrapper.PackageManagerWrapper;
|
||||
@@ -321,9 +322,13 @@ public class RecentAppsPreferenceController extends AbstractPreferenceController
|
||||
.setPackage(pkgName);
|
||||
|
||||
if (mPm.resolveActivity(launchIntent, 0) == null) {
|
||||
// Not visible on launcher -> likely not a user visible app, skip
|
||||
Log.d(TAG, "Not a user visible app, skipping " + pkgName);
|
||||
return false;
|
||||
// Not visible on launcher -> likely not a user visible app, skip if non-instant.
|
||||
final ApplicationsState.AppEntry appEntry =
|
||||
mApplicationsState.getEntry(pkgName, mUserId);
|
||||
if (!AppUtils.isInstant(appEntry.info)) {
|
||||
Log.d(TAG, "Not a user visible or instant app, skipping " + pkgName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.AppStateUsageBridge.UsageState;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
public class UsageAccessDetails extends AppInfoWithHeader implements OnPreferenceChangeListener,
|
||||
OnPreferenceClickListener {
|
||||
|
||||
@@ -93,7 +93,8 @@ public class AppActionButtonPreferenceController extends BasePreferenceControlle
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE;
|
||||
return AppUtils.isInstant(mParent.getPackageInfo().applicationInfo)
|
||||
? DISABLED_FOR_USER : AVAILABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,7 +23,7 @@ import com.android.settings.applications.AppStateInstallAppsBridge;
|
||||
import com.android.settings.applications.AppStateNotificationBridge;
|
||||
import com.android.settings.applications.AppStateOverlayBridge;
|
||||
import com.android.settings.applications.AppStatePowerBridge;
|
||||
import com.android.settings.applications.AppStateStorageAccessBridge;
|
||||
import com.android.settings.applications.AppStateDirectoryAccessBridge;
|
||||
import com.android.settings.applications.AppStateUsageBridge;
|
||||
import com.android.settings.applications.AppStateWriteSettingsBridge;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
@@ -66,7 +66,7 @@ public class AppFilterRegistry {
|
||||
public static final int FILTER_APPS_WITH_OVERLAY = 10;
|
||||
public static final int FILTER_APPS_WRITE_SETTINGS = 11;
|
||||
public static final int FILTER_APPS_INSTALL_SOURCES = 12;
|
||||
public static final int FILTER_APP_HAS_STORAGE_ACCESS = 13;
|
||||
public static final int FILTER_APP_HAS_DIRECTORY_ACCESS = 13;
|
||||
// Next id: 14
|
||||
|
||||
private static AppFilterRegistry sRegistry;
|
||||
@@ -158,10 +158,10 @@ public class AppFilterRegistry {
|
||||
FILTER_APPS_INSTALL_SOURCES,
|
||||
R.string.filter_install_sources_apps);
|
||||
|
||||
// Apps that interacted with storage access permissions (A.K.A. Scoped Directory Access)
|
||||
mFilters[FILTER_APP_HAS_STORAGE_ACCESS] = new AppFilterItem(
|
||||
AppStateStorageAccessBridge.FILTER_APP_HAS_STORAGE_ACCESS,
|
||||
FILTER_APP_HAS_STORAGE_ACCESS,
|
||||
// Apps that interacted with directory access permissions (A.K.A. Scoped Directory Access)
|
||||
mFilters[FILTER_APP_HAS_DIRECTORY_ACCESS] = new AppFilterItem(
|
||||
AppStateDirectoryAccessBridge.FILTER_APP_HAS_DIRECTORY_ACCESS,
|
||||
FILTER_APP_HAS_DIRECTORY_ACCESS,
|
||||
R.string.filter_install_sources_apps);
|
||||
}
|
||||
|
||||
@@ -185,8 +185,8 @@ public class AppFilterRegistry {
|
||||
return FILTER_APPS_WRITE_SETTINGS;
|
||||
case ManageApplications.LIST_TYPE_MANAGE_SOURCES:
|
||||
return FILTER_APPS_INSTALL_SOURCES;
|
||||
case ManageApplications.LIST_TYPE_STORAGE_ACCESS:
|
||||
return FILTER_APP_HAS_STORAGE_ACCESS;
|
||||
case ManageApplications.LIST_TYPE_DIRECTORY_ACCESS:
|
||||
return FILTER_APP_HAS_DIRECTORY_ACCESS;
|
||||
default:
|
||||
return FILTER_APPS_ALL;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ import com.android.settings.applications.AppStateInstallAppsBridge;
|
||||
import com.android.settings.applications.AppStateNotificationBridge;
|
||||
import com.android.settings.applications.AppStateOverlayBridge;
|
||||
import com.android.settings.applications.AppStatePowerBridge;
|
||||
import com.android.settings.applications.AppStateStorageAccessBridge;
|
||||
import com.android.settings.applications.AppStateDirectoryAccessBridge;
|
||||
import com.android.settings.applications.AppStateUsageBridge;
|
||||
import com.android.settings.applications.AppStateUsageBridge.UsageState;
|
||||
import com.android.settings.applications.AppStateWriteSettingsBridge;
|
||||
@@ -93,7 +93,7 @@ import com.android.settings.applications.DefaultAppSettings;
|
||||
import com.android.settings.applications.InstalledAppCounter;
|
||||
import com.android.settings.applications.InstalledAppDetails;
|
||||
import com.android.settings.applications.NotificationApps;
|
||||
import com.android.settings.applications.StorageAccessDetails;
|
||||
import com.android.settings.applications.DirectoryAccessDetails;
|
||||
import com.android.settings.applications.UsageAccessDetails;
|
||||
import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
|
||||
import com.android.settings.applications.appinfo.DrawOverlayDetails;
|
||||
@@ -206,7 +206,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
public static final int LIST_TYPE_GAMES = 9;
|
||||
public static final int LIST_TYPE_MOVIES = 10;
|
||||
public static final int LIST_TYPE_PHOTOGRAPHY = 11;
|
||||
public static final int LIST_TYPE_STORAGE_ACCESS = 12;
|
||||
public static final int LIST_TYPE_DIRECTORY_ACCESS = 12;
|
||||
|
||||
// List types that should show instant apps.
|
||||
public static final Set<Integer> LIST_TYPES_WITH_INSTANT = new ArraySet<>(Arrays.asList(
|
||||
@@ -282,9 +282,9 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
mListType = LIST_TYPE_PHOTOGRAPHY;
|
||||
mSortOrder = R.id.sort_order_size;
|
||||
mStorageType = args.getInt(EXTRA_STORAGE_TYPE, STORAGE_TYPE_DEFAULT);
|
||||
} else if (className.equals(Settings.StorageAccessSettingsActivity.class.getName())) {
|
||||
mListType = LIST_TYPE_STORAGE_ACCESS;
|
||||
screenTitle = R.string.storage_access;
|
||||
} else if (className.equals(Settings.DirectoryAccessSettingsActivity.class.getName())) {
|
||||
mListType = LIST_TYPE_DIRECTORY_ACCESS;
|
||||
screenTitle = R.string.directory_access;
|
||||
} else {
|
||||
mListType = LIST_TYPE_MAIN;
|
||||
}
|
||||
@@ -449,8 +449,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
return MetricsEvent.SYSTEM_ALERT_WINDOW_APPS;
|
||||
case LIST_TYPE_MANAGE_SOURCES:
|
||||
return MetricsEvent.MANAGE_EXTERNAL_SOURCES;
|
||||
case LIST_TYPE_STORAGE_ACCESS:
|
||||
return MetricsEvent.STORAGE_ACCESS;
|
||||
case LIST_TYPE_DIRECTORY_ACCESS:
|
||||
return MetricsEvent.DIRECTORY_ACCESS;
|
||||
default:
|
||||
return MetricsEvent.VIEW_UNKNOWN;
|
||||
}
|
||||
@@ -545,8 +545,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
case LIST_TYPE_PHOTOGRAPHY:
|
||||
startAppInfoFragment(AppStorageSettings.class, R.string.storage_photos_videos);
|
||||
break;
|
||||
case LIST_TYPE_STORAGE_ACCESS:
|
||||
startAppInfoFragment(StorageAccessDetails.class, R.string.storage_access);
|
||||
case LIST_TYPE_DIRECTORY_ACCESS:
|
||||
startAppInfoFragment(DirectoryAccessDetails.class, R.string.directory_access);
|
||||
break;
|
||||
|
||||
// TODO: Figure out if there is a way where we can spin up the profile's settings
|
||||
@@ -852,8 +852,8 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
mExtraInfoBridge = new AppStateWriteSettingsBridge(mContext, mState, this);
|
||||
} else if (mManageApplications.mListType == LIST_TYPE_MANAGE_SOURCES) {
|
||||
mExtraInfoBridge = new AppStateInstallAppsBridge(mContext, mState, this);
|
||||
} else if (mManageApplications.mListType == LIST_TYPE_STORAGE_ACCESS) {
|
||||
mExtraInfoBridge = new AppStateStorageAccessBridge(mState, this);
|
||||
} else if (mManageApplications.mListType == LIST_TYPE_DIRECTORY_ACCESS) {
|
||||
mExtraInfoBridge = new AppStateDirectoryAccessBridge(mState, this);
|
||||
} else {
|
||||
mExtraInfoBridge = null;
|
||||
}
|
||||
@@ -1255,7 +1255,7 @@ public class ManageApplications extends InstrumentedPreferenceFragment
|
||||
case LIST_TYPE_MANAGE_SOURCES:
|
||||
holder.setSummary(ExternalSourcesDetails.getPreferenceSummary(mContext, entry));
|
||||
break;
|
||||
case LIST_TYPE_STORAGE_ACCESS:
|
||||
case LIST_TYPE_DIRECTORY_ACCESS:
|
||||
holder.setSummary(null);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -33,10 +33,10 @@ import android.widget.ImageView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.widget.GearPreference;
|
||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH;
|
||||
|
||||
|
||||
@@ -23,9 +23,9 @@ import android.support.v7.preference.Preference;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
public class BluetoothDeviceRenamePreferenceController extends
|
||||
|
||||
@@ -27,12 +27,12 @@ import android.widget.Toast;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.widget.SwitchWidgetController;
|
||||
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||
import com.android.settingslib.WirelessUtils;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
|
||||
import com.android.settingslib.bluetooth.LocalBluetoothManager;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
/**
|
||||
* BluetoothEnabler is a helper to manage the Bluetooth on/off checkbox
|
||||
|
||||
@@ -23,9 +23,9 @@ import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
/**
|
||||
* Controller that shows received files
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
|
||||
package com.android.settings.core;
|
||||
|
||||
import com.android.settings.core.instrumentation.Instrumentable;
|
||||
import com.android.settings.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.Instrumentable;
|
||||
import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settingslib.core.lifecycle.ObservableActivity;
|
||||
|
||||
/**
|
||||
@@ -27,7 +28,8 @@ public abstract class InstrumentedActivity extends ObservableActivity implements
|
||||
|
||||
public InstrumentedActivity() {
|
||||
// Mixin that logs visibility change for activity.
|
||||
getLifecycle().addObserver(new VisibilityLoggerMixin(getMetricsCategory()));
|
||||
getLifecycle().addObserver(new VisibilityLoggerMixin(getMetricsCategory(),
|
||||
FeatureFactory.getFactory(this).getMetricsFeatureProvider()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,30 +18,28 @@ package com.android.settings.core;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.core.instrumentation.Instrumentable;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.survey.SurveyMixin;
|
||||
import com.android.settingslib.core.instrumentation.Instrumentable;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settingslib.core.lifecycle.ObservableFragment;
|
||||
|
||||
public abstract class InstrumentedFragment extends ObservableFragment implements Instrumentable {
|
||||
|
||||
protected MetricsFeatureProvider mMetricsFeatureProvider;
|
||||
|
||||
private final VisibilityLoggerMixin mVisibilityLoggerMixin;
|
||||
|
||||
public InstrumentedFragment() {
|
||||
// Mixin that logs visibility change for activity.
|
||||
mVisibilityLoggerMixin = new VisibilityLoggerMixin(getMetricsCategory());
|
||||
getLifecycle().addObserver(mVisibilityLoggerMixin);
|
||||
getLifecycle().addObserver(new SurveyMixin(this, getClass().getSimpleName()));
|
||||
}
|
||||
private VisibilityLoggerMixin mVisibilityLoggerMixin;
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
|
||||
mVisibilityLoggerMixin = new VisibilityLoggerMixin(getMetricsCategory(),
|
||||
mMetricsFeatureProvider);
|
||||
// Mixin that logs visibility change for activity.
|
||||
getLifecycle().addObserver(mVisibilityLoggerMixin);
|
||||
getLifecycle().addObserver(new SurveyMixin(this, getClass().getSimpleName()));
|
||||
super.onAttach(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,11 +23,11 @@ import android.support.v7.preference.PreferenceScreen;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settings.core.instrumentation.Instrumentable;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.survey.SurveyMixin;
|
||||
import com.android.settingslib.core.instrumentation.Instrumentable;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settingslib.core.lifecycle.ObservablePreferenceFragment;
|
||||
|
||||
/**
|
||||
@@ -44,19 +44,17 @@ public abstract class InstrumentedPreferenceFragment extends ObservablePreferenc
|
||||
// metrics placeholder value. Only use this for development.
|
||||
protected final int PLACEHOLDER_METRIC = 10000;
|
||||
|
||||
private final VisibilityLoggerMixin mVisibilityLoggerMixin;
|
||||
|
||||
public InstrumentedPreferenceFragment() {
|
||||
// Mixin that logs visibility change for activity.
|
||||
mVisibilityLoggerMixin = new VisibilityLoggerMixin(getMetricsCategory());
|
||||
getLifecycle().addObserver(mVisibilityLoggerMixin);
|
||||
getLifecycle().addObserver(new SurveyMixin(this, getClass().getSimpleName()));
|
||||
}
|
||||
private VisibilityLoggerMixin mVisibilityLoggerMixin;
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
|
||||
// Mixin that logs visibility change for activity.
|
||||
mVisibilityLoggerMixin = new VisibilityLoggerMixin(getMetricsCategory(),
|
||||
mMetricsFeatureProvider);
|
||||
getLifecycle().addObserver(mVisibilityLoggerMixin);
|
||||
getLifecycle().addObserver(new SurveyMixin(this, getClass().getSimpleName()));
|
||||
super.onAttach(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -44,7 +44,7 @@ import com.android.settings.applications.ManageDomainUrls;
|
||||
import com.android.settings.applications.NotificationApps;
|
||||
import com.android.settings.applications.ProcessStatsSummary;
|
||||
import com.android.settings.applications.ProcessStatsUi;
|
||||
import com.android.settings.applications.StorageAccessDetails;
|
||||
import com.android.settings.applications.DirectoryAccessDetails;
|
||||
import com.android.settings.applications.UsageAccessDetails;
|
||||
import com.android.settings.applications.VrListenerSettings;
|
||||
import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
|
||||
@@ -254,7 +254,7 @@ public class SettingsGateway {
|
||||
LockscreenDashboardFragment.class.getName(),
|
||||
BluetoothDeviceDetailsFragment.class.getName(),
|
||||
DataUsageList.class.getName(),
|
||||
StorageAccessDetails.class.getName()
|
||||
DirectoryAccessDetails.class.getName()
|
||||
};
|
||||
|
||||
public static final String[] SETTINGS_FOR_RESTRICTED = {
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.metrics.LogMaker;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
|
||||
/**
|
||||
* {@link LogWriter} that writes data to eventlog.
|
||||
*/
|
||||
public class EventLogWriter implements LogWriter {
|
||||
|
||||
private final MetricsLogger mMetricsLogger = new MetricsLogger();
|
||||
|
||||
public void visible(Context context, int source, int category) {
|
||||
final LogMaker logMaker = new LogMaker(category)
|
||||
.setType(MetricsProto.MetricsEvent.TYPE_OPEN)
|
||||
.addTaggedData(MetricsProto.MetricsEvent.FIELD_CONTEXT, source);
|
||||
MetricsLogger.action(logMaker);
|
||||
}
|
||||
|
||||
public void hidden(Context context, int category) {
|
||||
MetricsLogger.hidden(context, category);
|
||||
}
|
||||
|
||||
public void action(int category, int value, Pair<Integer, Object>... taggedData) {
|
||||
if (taggedData == null || taggedData.length == 0) {
|
||||
mMetricsLogger.action(category, value);
|
||||
} else {
|
||||
final LogMaker logMaker = new LogMaker(category)
|
||||
.setType(MetricsProto.MetricsEvent.TYPE_ACTION)
|
||||
.setSubtype(value);
|
||||
for (Pair<Integer, Object> pair : taggedData) {
|
||||
logMaker.addTaggedData(pair.first, pair.second);
|
||||
}
|
||||
mMetricsLogger.write(logMaker);
|
||||
}
|
||||
}
|
||||
|
||||
public void action(int category, boolean value, Pair<Integer, Object>... taggedData) {
|
||||
action(category, value ? 1 : 0, taggedData);
|
||||
}
|
||||
|
||||
public void action(Context context, int category, Pair<Integer, Object>... taggedData) {
|
||||
action(context, category, "", taggedData);
|
||||
}
|
||||
|
||||
public void actionWithSource(Context context, int source, int category) {
|
||||
final LogMaker logMaker = new LogMaker(category)
|
||||
.setType(MetricsProto.MetricsEvent.TYPE_ACTION);
|
||||
if (source != MetricsProto.MetricsEvent.VIEW_UNKNOWN) {
|
||||
logMaker.addTaggedData(MetricsProto.MetricsEvent.FIELD_CONTEXT, source);
|
||||
}
|
||||
MetricsLogger.action(logMaker);
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #action(int, int, Pair[])} */
|
||||
@Deprecated
|
||||
public void action(Context context, int category, int value) {
|
||||
MetricsLogger.action(context, category, value);
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #action(int, boolean, Pair[])} */
|
||||
@Deprecated
|
||||
public void action(Context context, int category, boolean value) {
|
||||
MetricsLogger.action(context, category, value);
|
||||
}
|
||||
|
||||
public void action(Context context, int category, String pkg,
|
||||
Pair<Integer, Object>... taggedData) {
|
||||
if (taggedData == null || taggedData.length == 0) {
|
||||
MetricsLogger.action(context, category, pkg);
|
||||
} else {
|
||||
final LogMaker logMaker = new LogMaker(category)
|
||||
.setType(MetricsProto.MetricsEvent.TYPE_ACTION)
|
||||
.setPackageName(pkg);
|
||||
for (Pair<Integer, Object> pair : taggedData) {
|
||||
logMaker.addTaggedData(pair.first, pair.second);
|
||||
}
|
||||
MetricsLogger.action(logMaker);
|
||||
}
|
||||
}
|
||||
|
||||
public void count(Context context, String name, int value) {
|
||||
MetricsLogger.count(context, name, value);
|
||||
}
|
||||
|
||||
public void histogram(Context context, String name, int bucket) {
|
||||
MetricsLogger.histogram(context, name, bucket);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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;
|
||||
|
||||
public interface Instrumentable {
|
||||
|
||||
int METRICS_CATEGORY_UNKNOWN = 0;
|
||||
|
||||
/**
|
||||
* Instrumented name for a view as defined in
|
||||
* {@link com.android.internal.logging.nano.MetricsProto.MetricsEvent}.
|
||||
*/
|
||||
int getMetricsCategory();
|
||||
}
|
||||
@@ -19,6 +19,9 @@ import android.content.Context;
|
||||
|
||||
import com.android.settings.DialogCreatable;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.Instrumentable;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settingslib.core.lifecycle.ObservableDialogFragment;
|
||||
|
||||
public abstract class InstrumentedDialogFragment extends ObservableDialogFragment
|
||||
@@ -38,13 +41,15 @@ public abstract class InstrumentedDialogFragment extends ObservableDialogFragmen
|
||||
public InstrumentedDialogFragment(DialogCreatable dialogCreatable, int dialogId) {
|
||||
mDialogCreatable = dialogCreatable;
|
||||
mDialogId = dialogId;
|
||||
mLifecycle.addObserver(new VisibilityLoggerMixin(getMetricsCategory()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
|
||||
mMetricsFeatureProvider = FeatureFactory.getFactory(context)
|
||||
.getMetricsFeatureProvider();
|
||||
mLifecycle.addObserver(new VisibilityLoggerMixin(getMetricsCategory(),
|
||||
mMetricsFeatureProvider));
|
||||
mLifecycle.onAttach(context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.util.Pair;
|
||||
|
||||
/**
|
||||
* Generic log writer interface.
|
||||
*/
|
||||
public interface LogWriter {
|
||||
|
||||
/**
|
||||
* Logs a visibility event when view becomes visible.
|
||||
*/
|
||||
void visible(Context context, int source, int category);
|
||||
|
||||
/**
|
||||
* Logs a visibility event when view becomes hidden.
|
||||
*/
|
||||
void hidden(Context context, int category);
|
||||
|
||||
/**
|
||||
* Logs a user action.
|
||||
*/
|
||||
void action(int category, int value, Pair<Integer, Object>... taggedData);
|
||||
|
||||
/**
|
||||
* Logs a user action.
|
||||
*/
|
||||
void action(int category, boolean value, Pair<Integer, Object>... taggedData);
|
||||
|
||||
/**
|
||||
* Logs an user action.
|
||||
*/
|
||||
void action(Context context, int category, Pair<Integer, Object>... taggedData);
|
||||
|
||||
/**
|
||||
* Logs an user action.
|
||||
*/
|
||||
void actionWithSource(Context context, int source, int category);
|
||||
|
||||
/**
|
||||
* Logs an user action.
|
||||
* @deprecated use {@link #action(int, int, Pair[])}
|
||||
*/
|
||||
@Deprecated
|
||||
void action(Context context, int category, int value);
|
||||
|
||||
/**
|
||||
* Logs an user action.
|
||||
* @deprecated use {@link #action(int, boolean, Pair[])}
|
||||
*/
|
||||
@Deprecated
|
||||
void action(Context context, int category, boolean value);
|
||||
|
||||
/**
|
||||
* Logs an user action.
|
||||
*/
|
||||
void action(Context context, int category, String pkg, Pair<Integer, Object>... taggedData);
|
||||
|
||||
/**
|
||||
* Logs a count.
|
||||
*/
|
||||
void count(Context context, String name, int value);
|
||||
|
||||
/**
|
||||
* Logs a histogram event.
|
||||
*/
|
||||
void histogram(Context context, String name, int bucket);
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* FeatureProvider for metrics.
|
||||
*/
|
||||
public class MetricsFeatureProvider {
|
||||
private List<LogWriter> mLoggerWriters;
|
||||
|
||||
public MetricsFeatureProvider() {
|
||||
mLoggerWriters = new ArrayList<>();
|
||||
installLogWriters();
|
||||
}
|
||||
|
||||
protected void installLogWriters() {
|
||||
mLoggerWriters.add(new EventLogWriter());
|
||||
}
|
||||
|
||||
public void visible(Context context, int source, int category) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.visible(context, source, category);
|
||||
}
|
||||
}
|
||||
|
||||
public void hidden(Context context, int category) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.hidden(context, category);
|
||||
}
|
||||
}
|
||||
|
||||
public void actionWithSource(Context context, int source, int category) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.actionWithSource(context, source, category);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a user action. Includes the elapsed time since the containing
|
||||
* fragment has been visible.
|
||||
*/
|
||||
public void action(VisibilityLoggerMixin visibilityLogger, int category, int value) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.action(category, value,
|
||||
sinceVisibleTaggedData(visibilityLogger.elapsedTimeSinceVisible()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a user action. Includes the elapsed time since the containing
|
||||
* fragment has been visible.
|
||||
*/
|
||||
public void action(VisibilityLoggerMixin visibilityLogger, int category, boolean value) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.action(category, value,
|
||||
sinceVisibleTaggedData(visibilityLogger.elapsedTimeSinceVisible()));
|
||||
}
|
||||
}
|
||||
|
||||
public void action(Context context, int category, Pair<Integer, Object>... taggedData) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.action(context, category, taggedData);
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #action(VisibilityLoggerMixin, int, int)} */
|
||||
@Deprecated
|
||||
public void action(Context context, int category, int value) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.action(context, category, value);
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #action(VisibilityLoggerMixin, int, boolean)} */
|
||||
@Deprecated
|
||||
public void action(Context context, int category, boolean value) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.action(context, category, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void action(Context context, int category, String pkg,
|
||||
Pair<Integer, Object>... taggedData) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.action(context, category, pkg, taggedData);
|
||||
}
|
||||
}
|
||||
|
||||
public void count(Context context, String name, int value) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.count(context, name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void histogram(Context context, String name, int bucket) {
|
||||
for (LogWriter writer : mLoggerWriters) {
|
||||
writer.histogram(context, name, bucket);
|
||||
}
|
||||
}
|
||||
|
||||
public int getMetricsCategory(Object object) {
|
||||
if (object == null || !(object instanceof Instrumentable)) {
|
||||
return MetricsEvent.VIEW_UNKNOWN;
|
||||
}
|
||||
return ((Instrumentable) object).getMetricsCategory();
|
||||
}
|
||||
|
||||
public void logDashboardStartIntent(Context context, Intent intent,
|
||||
int sourceMetricsCategory) {
|
||||
if (intent == null) {
|
||||
return;
|
||||
}
|
||||
final ComponentName cn = intent.getComponent();
|
||||
if (cn == null) {
|
||||
final String action = intent.getAction();
|
||||
if (TextUtils.isEmpty(action)) {
|
||||
// Not loggable
|
||||
return;
|
||||
}
|
||||
action(context, MetricsEvent.ACTION_SETTINGS_TILE_CLICK, action,
|
||||
Pair.create(MetricsEvent.FIELD_CONTEXT, sourceMetricsCategory));
|
||||
return;
|
||||
} else if (TextUtils.equals(cn.getPackageName(), context.getPackageName())) {
|
||||
// Going to a Setting internal page, skip click logging in favor of page's own
|
||||
// visibility logging.
|
||||
return;
|
||||
}
|
||||
action(context, MetricsEvent.ACTION_SETTINGS_TILE_CLICK, cn.flattenToString(),
|
||||
Pair.create(MetricsEvent.FIELD_CONTEXT, sourceMetricsCategory));
|
||||
}
|
||||
|
||||
private Pair<Integer, Object> sinceVisibleTaggedData(long timestamp) {
|
||||
return Pair.create(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS, timestamp);
|
||||
}
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
|
||||
public class SharedPreferencesLogger implements SharedPreferences {
|
||||
|
||||
private static final String LOG_TAG = "SharedPreferencesLogger";
|
||||
|
||||
private final String mTag;
|
||||
private final Context mContext;
|
||||
private final MetricsFeatureProvider mMetricsFeature;
|
||||
private final Set<String> mPreferenceKeySet;
|
||||
|
||||
public SharedPreferencesLogger(Context context, String tag) {
|
||||
mContext = context;
|
||||
mTag = tag;
|
||||
mMetricsFeature = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
|
||||
mPreferenceKeySet = new ConcurrentSkipListSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ?> getAll() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(String key, @Nullable String defValue) {
|
||||
return defValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getStringSet(String key, @Nullable Set<String> defValues) {
|
||||
return defValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(String key, int defValue) {
|
||||
return defValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(String key, long defValue) {
|
||||
return defValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(String key, float defValue) {
|
||||
return defValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String key, boolean defValue) {
|
||||
return defValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(String key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor edit() {
|
||||
return new EditorLogger();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerOnSharedPreferenceChangeListener(
|
||||
OnSharedPreferenceChangeListener listener) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterOnSharedPreferenceChangeListener(
|
||||
OnSharedPreferenceChangeListener listener) {
|
||||
}
|
||||
|
||||
private void logValue(String key, Object value) {
|
||||
logValue(key, value, false /* forceLog */);
|
||||
}
|
||||
|
||||
private void logValue(String key, Object value, boolean forceLog) {
|
||||
final String prefKey = buildPrefKey(mTag, key);
|
||||
if (!forceLog && !mPreferenceKeySet.contains(prefKey)) {
|
||||
// Pref key doesn't exist in set, this is initial display so we skip metrics but
|
||||
// keeps track of this key.
|
||||
mPreferenceKeySet.add(prefKey);
|
||||
return;
|
||||
}
|
||||
// TODO: Remove count logging to save some resource.
|
||||
mMetricsFeature.count(mContext, buildCountName(prefKey, value), 1);
|
||||
|
||||
final Pair<Integer, Object> valueData;
|
||||
if (value instanceof Long) {
|
||||
final Long longVal = (Long) value;
|
||||
final int intVal;
|
||||
if (longVal > Integer.MAX_VALUE) {
|
||||
intVal = Integer.MAX_VALUE;
|
||||
} else if (longVal < Integer.MIN_VALUE) {
|
||||
intVal = Integer.MIN_VALUE;
|
||||
} else {
|
||||
intVal = longVal.intValue();
|
||||
}
|
||||
valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
|
||||
intVal);
|
||||
} else if (value instanceof Integer) {
|
||||
valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
|
||||
value);
|
||||
} else if (value instanceof Boolean) {
|
||||
valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
|
||||
(Boolean) value ? 1 : 0);
|
||||
} else if (value instanceof Float) {
|
||||
valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE,
|
||||
value);
|
||||
} else if (value instanceof String) {
|
||||
Log.d(LOG_TAG, "Tried to log string preference " + prefKey + " = " + value);
|
||||
valueData = null;
|
||||
} else {
|
||||
Log.w(LOG_TAG, "Tried to log unloggable object" + value);
|
||||
valueData = null;
|
||||
}
|
||||
if (valueData != null) {
|
||||
// Pref key exists in set, log it's change in metrics.
|
||||
mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE,
|
||||
Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey),
|
||||
valueData);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void logPackageName(String key, String value) {
|
||||
final String prefKey = mTag + "/" + key;
|
||||
mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE, value,
|
||||
Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey));
|
||||
}
|
||||
|
||||
private void safeLogValue(String key, String value) {
|
||||
new AsyncPackageCheck().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, key, value);
|
||||
}
|
||||
|
||||
public static String buildCountName(String prefKey, Object value) {
|
||||
return prefKey + "|" + value;
|
||||
}
|
||||
|
||||
public static String buildPrefKey(String tag, String key) {
|
||||
return tag + "/" + key;
|
||||
}
|
||||
|
||||
private class AsyncPackageCheck extends AsyncTask<String, Void, Void> {
|
||||
@Override
|
||||
protected Void doInBackground(String... params) {
|
||||
String key = params[0];
|
||||
String value = params[1];
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
try {
|
||||
// Check if this might be a component.
|
||||
ComponentName name = ComponentName.unflattenFromString(value);
|
||||
if (value != null) {
|
||||
value = name.getPackageName();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
pm.getPackageInfo(value, PackageManager.MATCH_ANY_USER);
|
||||
logPackageName(key, value);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
// Clearly not a package, and it's unlikely this preference is in prefSet, so
|
||||
// lets force log it.
|
||||
logValue(key, value, true /* forceLog */);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class EditorLogger implements Editor {
|
||||
@Override
|
||||
public Editor putString(String key, @Nullable String value) {
|
||||
safeLogValue(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putStringSet(String key, @Nullable Set<String> values) {
|
||||
safeLogValue(key, TextUtils.join(",", values));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putInt(String key, int value) {
|
||||
logValue(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putLong(String key, long value) {
|
||||
logValue(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putFloat(String key, float value) {
|
||||
logValue(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor putBoolean(String key, boolean value) {
|
||||
logValue(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor remove(String key) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor clear() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean commit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnAttach;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
|
||||
import static com.android.settings.core.instrumentation.Instrumentable.METRICS_CATEGORY_UNKNOWN;
|
||||
|
||||
/**
|
||||
* Logs visibility change of a fragment.
|
||||
*/
|
||||
public class VisibilityLoggerMixin implements LifecycleObserver, OnResume, OnPause, OnAttach {
|
||||
|
||||
private static final String TAG = "VisibilityLoggerMixin";
|
||||
|
||||
private final int mMetricsCategory;
|
||||
|
||||
private MetricsFeatureProvider mMetricsFeature;
|
||||
private int mSourceMetricsCategory = MetricsProto.MetricsEvent.VIEW_UNKNOWN;
|
||||
private long mVisibleTimestamp;
|
||||
|
||||
public VisibilityLoggerMixin(int metricsCategory) {
|
||||
// MetricsFeature will be set during onAttach.
|
||||
this(metricsCategory, null /* metricsFeature */);
|
||||
}
|
||||
|
||||
public VisibilityLoggerMixin(int metricsCategory, MetricsFeatureProvider metricsFeature) {
|
||||
mMetricsCategory = metricsCategory;
|
||||
mMetricsFeature = metricsFeature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
mMetricsFeature = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
mVisibleTimestamp = SystemClock.elapsedRealtime();
|
||||
if (mMetricsFeature != null && mMetricsCategory != METRICS_CATEGORY_UNKNOWN) {
|
||||
mMetricsFeature.visible(null /* context */, mSourceMetricsCategory, mMetricsCategory);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mVisibleTimestamp = 0;
|
||||
if (mMetricsFeature != null && mMetricsCategory != METRICS_CATEGORY_UNKNOWN) {
|
||||
mMetricsFeature.hidden(null /* context */, mMetricsCategory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets source metrics category for this logger. Source is the caller that opened this UI.
|
||||
*/
|
||||
public void setSourceMetricsCategory(Activity activity) {
|
||||
if (mSourceMetricsCategory != MetricsProto.MetricsEvent.VIEW_UNKNOWN || activity == null) {
|
||||
return;
|
||||
}
|
||||
final Intent intent = activity.getIntent();
|
||||
if (intent == null) {
|
||||
return;
|
||||
}
|
||||
mSourceMetricsCategory = intent.getIntExtra(SettingsActivity.EXTRA_SOURCE_METRICS_CATEGORY,
|
||||
MetricsProto.MetricsEvent.VIEW_UNKNOWN);
|
||||
}
|
||||
|
||||
/** Returns elapsed time since onResume() */
|
||||
public long elapsedTimeSinceVisible() {
|
||||
if (mVisibleTimestamp == 0) {
|
||||
return 0;
|
||||
}
|
||||
return SystemClock.elapsedRealtime() - mVisibleTimestamp;
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,6 @@ import android.widget.TextView;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.R.id;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.dashboard.DashboardData.SuggestionConditionHeaderData;
|
||||
import com.android.settings.dashboard.conditional.Condition;
|
||||
import com.android.settings.dashboard.conditional.ConditionAdapter;
|
||||
@@ -50,6 +49,7 @@ import com.android.settings.dashboard.suggestions.SuggestionControllerMixin;
|
||||
import com.android.settings.dashboard.suggestions.SuggestionDismissController;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.drawer.DashboardCategory;
|
||||
import com.android.settingslib.drawer.Tile;
|
||||
|
||||
|
||||
@@ -39,13 +39,13 @@ import android.widget.TextView;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.R.id;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.dashboard.DashboardDataV2.ConditionHeaderData;
|
||||
import com.android.settings.dashboard.conditional.Condition;
|
||||
import com.android.settings.dashboard.conditional.ConditionAdapterV2;
|
||||
import com.android.settings.dashboard.suggestions.SuggestionAdapterV2;
|
||||
import com.android.settings.dashboard.suggestions.SuggestionControllerMixin;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
|
||||
@@ -305,7 +305,8 @@ public class DashboardAdapterV2 extends RecyclerView.Adapter<DashboardAdapterV2.
|
||||
void onBindSuggestion(final SuggestionContainerHolder holder, int position) {
|
||||
// If there is suggestions to show, it will be at position 0 as we don't show the suggestion
|
||||
// header anymore.
|
||||
final List<Suggestion> suggestions = mDashboardData.getSuggestions();
|
||||
final List<Suggestion> suggestions =
|
||||
(List<Suggestion>) mDashboardData.getItemEntityByPosition(position);
|
||||
final int suggestionCount = suggestions.size();
|
||||
if (suggestions != null && suggestionCount > 0) {
|
||||
holder.summary.setText(""+suggestionCount);
|
||||
|
||||
@@ -41,8 +41,9 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.core.FeatureFlags;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settingslib.drawer.CategoryManager;
|
||||
import com.android.settingslib.drawer.DashboardCategory;
|
||||
import com.android.settingslib.drawer.ProfileSelectDialog;
|
||||
@@ -159,7 +160,8 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
|
||||
pref.setFragment(clsName);
|
||||
} else if (tile.intent != null) {
|
||||
final Intent intent = new Intent(tile.intent);
|
||||
intent.putExtra(SettingsActivity.EXTRA_SOURCE_METRICS_CATEGORY, sourceMetricsCategory);
|
||||
intent.putExtra(VisibilityLoggerMixin.EXTRA_SOURCE_METRICS_CATEGORY,
|
||||
sourceMetricsCategory);
|
||||
if (action != null) {
|
||||
intent.setAction(action);
|
||||
}
|
||||
@@ -208,7 +210,7 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
|
||||
return;
|
||||
}
|
||||
final Intent intent = new Intent(tile.intent)
|
||||
.putExtra(SettingsActivity.EXTRA_SOURCE_METRICS_CATEGORY,
|
||||
.putExtra(VisibilityLoggerMixin.EXTRA_SOURCE_METRICS_CATEGORY,
|
||||
MetricsEvent.DASHBOARD_SUMMARY)
|
||||
.putExtra(SettingsDrawerActivity.EXTRA_SHOW_MENU, true)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
|
||||
@@ -1,205 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.dashboard;
|
||||
|
||||
import static android.provider.SearchIndexablesContract.SITE_MAP_COLUMNS;
|
||||
import static com.android.settings.dashboard.DashboardFragmentRegistry.CATEGORY_KEY_TO_PARENT_MAP;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.provider.SearchIndexablesContract.SiteMapColumns;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.annotation.WorkerThread;
|
||||
import android.support.v4.util.ArrayMap;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.search.IndexDatabaseHelper;
|
||||
import com.android.settings.search.IndexDatabaseHelper.IndexColumns;
|
||||
import com.android.settingslib.drawer.DashboardCategory;
|
||||
import com.android.settingslib.drawer.Tile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A manager class that maintains a "site map" and look up breadcrumb for a certain page on demand.
|
||||
* <p/>
|
||||
* The methods on this class can only be called on a background thread.
|
||||
*/
|
||||
public class SiteMapManager {
|
||||
|
||||
private static final String TAG = "SiteMapManager";
|
||||
private static final boolean DEBUG_TIMING = false;
|
||||
|
||||
private static final String[] CLASS_TO_SCREEN_TITLE_COLUMNS = {
|
||||
IndexColumns.CLASS_NAME,
|
||||
IndexColumns.SCREEN_TITLE,
|
||||
};
|
||||
|
||||
private final List<SiteMapPair> mPairs = new ArrayList<>();
|
||||
|
||||
private boolean mInitialized;
|
||||
|
||||
/**
|
||||
* Given a fragment class name and its screen title, build a breadcrumb from Settings root to
|
||||
* this screen.
|
||||
* <p/>
|
||||
* Not all screens have a full breadcrumb path leading up to root, it's because either some
|
||||
* page in the breadcrumb path is not indexed, or it's only reachable via search.
|
||||
*/
|
||||
@WorkerThread
|
||||
public synchronized List<String> buildBreadCrumb(Context context, String clazz,
|
||||
String screenTitle) {
|
||||
init(context);
|
||||
final long startTime = System.currentTimeMillis();
|
||||
final List<String> breadcrumbs = new ArrayList<>();
|
||||
if (!mInitialized) {
|
||||
Log.w(TAG, "SiteMap is not initialized yet, skipping");
|
||||
return breadcrumbs;
|
||||
}
|
||||
breadcrumbs.add(screenTitle);
|
||||
String currentClass = clazz;
|
||||
String currentTitle = screenTitle;
|
||||
// Look up current page's parent, if found add it to breadcrumb string list, and repeat.
|
||||
while (true) {
|
||||
final SiteMapPair pair = lookUpParent(currentClass, currentTitle);
|
||||
if (pair == null) {
|
||||
if (DEBUG_TIMING) {
|
||||
Log.d(TAG, "BreadCrumb timing: " + (System.currentTimeMillis() - startTime));
|
||||
}
|
||||
return breadcrumbs;
|
||||
}
|
||||
breadcrumbs.add(0, pair.parentTitle);
|
||||
currentClass = pair.parentClass;
|
||||
currentTitle = pair.parentTitle;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a list of {@link SiteMapPair}s. Each pair knows about a single parent-child
|
||||
* page relationship.
|
||||
*
|
||||
* We get the knowledge of such mPairs from 2 sources:
|
||||
* 1. Static indexing time: we know which page(s) a parent can open by parsing its pref xml.
|
||||
* 2. IA: We know from {@link DashboardFeatureProvider} which page can be dynamically
|
||||
* injected to where.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@WorkerThread
|
||||
synchronized void init(Context context) {
|
||||
if (mInitialized) {
|
||||
// Make sure only init once.
|
||||
return;
|
||||
}
|
||||
final long startTime = System.currentTimeMillis();
|
||||
// First load site map from static index table.
|
||||
final Context appContext = context.getApplicationContext();
|
||||
final SQLiteDatabase db = IndexDatabaseHelper.getInstance(appContext).getReadableDatabase();
|
||||
Cursor sitemap = db.query(IndexDatabaseHelper.Tables.TABLE_SITE_MAP, SITE_MAP_COLUMNS, null,
|
||||
null, null, null, null);
|
||||
while (sitemap.moveToNext()) {
|
||||
final SiteMapPair pair = new SiteMapPair(
|
||||
sitemap.getString(sitemap.getColumnIndex(SiteMapColumns.PARENT_CLASS)),
|
||||
sitemap.getString(sitemap.getColumnIndex(SiteMapColumns.PARENT_TITLE)),
|
||||
sitemap.getString(sitemap.getColumnIndex(SiteMapColumns.CHILD_CLASS)),
|
||||
sitemap.getString(sitemap.getColumnIndex(SiteMapColumns.CHILD_TITLE)));
|
||||
mPairs.add(pair);
|
||||
}
|
||||
sitemap.close();
|
||||
|
||||
// Then prepare a local map that contains class name -> screen title mapping. This is needed
|
||||
// to figure out the display name for any fragment if it's injected dynamically through IA.
|
||||
final Map<String, String> classToTitleMap = new ArrayMap<>();
|
||||
final Cursor titleQuery = db.query(IndexDatabaseHelper.Tables.TABLE_PREFS_INDEX,
|
||||
CLASS_TO_SCREEN_TITLE_COLUMNS, null, null, null, null, null);
|
||||
while (titleQuery.moveToNext()) {
|
||||
classToTitleMap.put(
|
||||
titleQuery.getString(titleQuery.getColumnIndex(IndexColumns.CLASS_NAME)),
|
||||
titleQuery.getString(titleQuery.getColumnIndex(IndexColumns.SCREEN_TITLE)));
|
||||
}
|
||||
titleQuery.close();
|
||||
|
||||
// Loop through all IA categories and pages and build additional SiteMapPairs
|
||||
List<DashboardCategory> categories = FeatureFactory.getFactory(context)
|
||||
.getDashboardFeatureProvider(context).getAllCategories();
|
||||
|
||||
for (DashboardCategory category : categories) {
|
||||
// Find the category key first.
|
||||
final String parentClass = CATEGORY_KEY_TO_PARENT_MAP.get(category.key);
|
||||
if (parentClass == null) {
|
||||
continue;
|
||||
}
|
||||
// Use the key to look up parent (which page hosts this key)
|
||||
final String parentName = classToTitleMap.get(parentClass);
|
||||
if (parentName == null) {
|
||||
continue;
|
||||
}
|
||||
// Build parent-child mPairs for all children listed under this key.
|
||||
for (Tile tile : category.getTiles()) {
|
||||
final String childTitle = tile.title.toString();
|
||||
String childClass = null;
|
||||
if (tile.metaData != null) {
|
||||
childClass = tile.metaData.getString(
|
||||
SettingsActivity.META_DATA_KEY_FRAGMENT_CLASS);
|
||||
}
|
||||
if (childClass == null) {
|
||||
continue;
|
||||
}
|
||||
mPairs.add(new SiteMapPair(parentClass, parentName, childClass, childTitle));
|
||||
}
|
||||
}
|
||||
// Done.
|
||||
mInitialized = true;
|
||||
if (DEBUG_TIMING) {
|
||||
Log.d(TAG, "Init timing: " + (System.currentTimeMillis() - startTime));
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private SiteMapPair lookUpParent(String clazz, String title) {
|
||||
for (SiteMapPair pair : mPairs) {
|
||||
if (TextUtils.equals(pair.childClass, clazz)
|
||||
&& TextUtils.equals(title, pair.childTitle)) {
|
||||
return pair;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data model for a parent-child page pair.
|
||||
*/
|
||||
private static class SiteMapPair {
|
||||
public final String parentClass;
|
||||
public final String parentTitle;
|
||||
public final String childClass;
|
||||
public final String childTitle;
|
||||
|
||||
public SiteMapPair(String parentClass, String parentTitle, String childClass,
|
||||
String childTitle) {
|
||||
this.parentClass = parentClass;
|
||||
this.parentTitle = parentTitle;
|
||||
this.childClass = childClass;
|
||||
this.childTitle = childTitle;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,8 @@ import android.os.PersistableBundle;
|
||||
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
public abstract class Condition {
|
||||
|
||||
|
||||
@@ -27,13 +27,13 @@ import android.widget.Button;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.dashboard.DashboardAdapter;
|
||||
import com.android.settings.dashboard.DashboardAdapter.DashboardItemHolder;
|
||||
import com.android.settings.dashboard.DashboardData;
|
||||
import com.android.settings.dashboard.DashboardData.HeaderMode;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.WirelessUtils;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -27,10 +27,10 @@ import android.widget.Button;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.dashboard.DashboardAdapterV2.DashboardItemHolder;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.WirelessUtils;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -27,10 +27,10 @@ import android.view.ViewGroup;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.dashboard.DashboardAdapter.DashboardItemHolder;
|
||||
import com.android.settings.dashboard.DashboardAdapter.IconCache;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -31,10 +31,10 @@ import android.widget.LinearLayout;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.dashboard.DashboardAdapterV2.DashboardItemHolder;
|
||||
import com.android.settings.dashboard.DashboardAdapterV2.IconCache;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
|
||||
@@ -56,10 +56,7 @@ public class SuggestionAdapterV2 extends RecyclerView.Adapter<DashboardItemHolde
|
||||
private final ArrayList<String> mSuggestionsShownLogged;
|
||||
private final SuggestionControllerMixin mSuggestionControllerMixin;
|
||||
private final Callback mCallback;
|
||||
private final int mMultipleCardsMarginEnd;
|
||||
private final int mWidthSingleCard;
|
||||
private final int mWidthTwoCards;
|
||||
private final int mWidthMultipleCards;
|
||||
private final CardConfig mConfig;
|
||||
|
||||
private List<Suggestion> mSuggestions;
|
||||
|
||||
@@ -89,13 +86,7 @@ public class SuggestionAdapterV2 extends RecyclerView.Adapter<DashboardItemHolde
|
||||
if (lifecycle != null) {
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
|
||||
final Resources res = mContext.getResources();
|
||||
mMultipleCardsMarginEnd = res.getDimensionPixelOffset(R.dimen.suggestion_card_margin_end);
|
||||
mWidthSingleCard = res.getDimensionPixelOffset(R.dimen.suggestion_card_width_one_card);
|
||||
mWidthTwoCards = res.getDimensionPixelOffset(R.dimen.suggestion_card_width_two_cards);
|
||||
mWidthMultipleCards =
|
||||
res.getDimensionPixelOffset(R.dimen.suggestion_card_width_multiple_cards);
|
||||
mConfig = CardConfig.get(context);
|
||||
|
||||
setHasStableIds(true);
|
||||
}
|
||||
@@ -116,7 +107,7 @@ public class SuggestionAdapterV2 extends RecyclerView.Adapter<DashboardItemHolde
|
||||
mContext, MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, id);
|
||||
mSuggestionsShownLogged.add(id);
|
||||
}
|
||||
setCardWidthAndMargin(holder, suggestionCount);
|
||||
mConfig.setCardLayout(holder, suggestionCount, position);
|
||||
holder.icon.setImageDrawable(mCache.getIcon(suggestion.getIcon()));
|
||||
holder.title.setText(suggestion.getTitle());
|
||||
holder.title.setSingleLine(suggestionCount == 1);
|
||||
@@ -220,12 +211,61 @@ public class SuggestionAdapterV2 extends RecyclerView.Adapter<DashboardItemHolde
|
||||
return mSuggestions;
|
||||
}
|
||||
|
||||
private void setCardWidthAndMargin(DashboardItemHolder holder, int suggestionCount) {
|
||||
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||
suggestionCount == 1
|
||||
? mWidthSingleCard : suggestionCount == 2 ? mWidthTwoCards : mWidthMultipleCards,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
params.setMarginEnd(suggestionCount == 1 ? 0 : mMultipleCardsMarginEnd);
|
||||
holder.itemView.setLayoutParams(params);
|
||||
private static class CardConfig {
|
||||
// Card start/end margin
|
||||
private final int mMarginInner;
|
||||
private final int mMarginOuter;
|
||||
// Card width for different numbers of cards
|
||||
private final int mWidthSingleCard;
|
||||
private final int mWidthTwoCards;
|
||||
private final int mWidthMultipleCards;
|
||||
// padding between icon and title
|
||||
private final int mPaddingTitleTopSingleCard;
|
||||
private final int mPaddingTitleTopMultipleCards;
|
||||
|
||||
private static CardConfig sConfig;
|
||||
|
||||
private CardConfig(Context context) {
|
||||
final Resources res = context.getResources();
|
||||
mMarginInner =
|
||||
res.getDimensionPixelOffset(R.dimen.suggestion_card_inner_margin);
|
||||
mMarginOuter =
|
||||
res.getDimensionPixelOffset(R.dimen.suggestion_card_outer_margin);
|
||||
mWidthSingleCard = res.getDimensionPixelOffset(R.dimen.suggestion_card_width_one_card);
|
||||
mWidthTwoCards = res.getDimensionPixelOffset(R.dimen.suggestion_card_width_two_cards);
|
||||
mWidthMultipleCards =
|
||||
res.getDimensionPixelOffset(R.dimen.suggestion_card_width_multiple_cards);
|
||||
mPaddingTitleTopSingleCard =
|
||||
res.getDimensionPixelOffset(R.dimen.suggestion_card_title_padding_bottom_one_card);
|
||||
mPaddingTitleTopMultipleCards = res.getDimensionPixelOffset(
|
||||
R.dimen.suggestion_card_title_padding_bottom_multiple_cards);
|
||||
}
|
||||
|
||||
public static CardConfig get(Context context) {
|
||||
if (sConfig == null) {
|
||||
sConfig = new CardConfig(context);
|
||||
}
|
||||
return sConfig;
|
||||
}
|
||||
|
||||
private void setCardLayout(DashboardItemHolder holder, int suggestionCount,
|
||||
int position) {
|
||||
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||
suggestionCount == 1
|
||||
? mWidthSingleCard : suggestionCount == 2
|
||||
? mWidthTwoCards : mWidthMultipleCards,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
if (suggestionCount == 1) {
|
||||
params.setMarginStart(mMarginOuter);
|
||||
params.setMarginEnd(mMarginOuter);
|
||||
} else {
|
||||
params.setMarginStart(
|
||||
position == 0 ? mMarginOuter : mMarginInner);
|
||||
params.setMarginEnd(position == suggestionCount - 1 ? mMarginOuter : 0);
|
||||
}
|
||||
holder.itemView.setLayoutParams(params);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ import com.android.settings.Settings.DoubleTapPowerSuggestionActivity;
|
||||
import com.android.settings.Settings.DoubleTwistSuggestionActivity;
|
||||
import com.android.settings.Settings.NightDisplaySuggestionActivity;
|
||||
import com.android.settings.Settings.SwipeToNotificationSuggestionActivity;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.fingerprint.FingerprintEnrollSuggestionActivity;
|
||||
import com.android.settings.fingerprint.FingerprintSuggestionActivity;
|
||||
import com.android.settings.gestures.DoubleTapPowerPreferenceController;
|
||||
@@ -49,6 +48,7 @@ import com.android.settings.password.ScreenLockSuggestionActivity;
|
||||
import com.android.settings.support.NewDeviceIntroSuggestionActivity;
|
||||
import com.android.settings.wallpaper.WallpaperSuggestionActivity;
|
||||
import com.android.settings.wifi.WifiCallingSuggestionActivity;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.drawer.Tile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -25,8 +25,8 @@ import android.os.RemoteException;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -204,6 +204,10 @@ public class DataSaverBackend {
|
||||
public void onRestrictBackgroundChanged(final boolean isDataSaving) throws RemoteException {
|
||||
ThreadUtils.postOnMainThread(() -> handleRestrictBackgroundChanged(isDataSaving));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue) {
|
||||
}
|
||||
};
|
||||
|
||||
public interface Listener {
|
||||
|
||||
@@ -35,8 +35,9 @@ import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.instrumentation.Instrumentable;
|
||||
import com.android.settings.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.Instrumentable;
|
||||
import com.android.settingslib.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settingslib.datetime.ZoneGetter;
|
||||
|
||||
import java.text.Collator;
|
||||
@@ -57,8 +58,7 @@ public class ZonePicker extends ListFragment implements Instrumentable {
|
||||
|
||||
private static final int MENU_TIMEZONE = Menu.FIRST+1;
|
||||
private static final int MENU_ALPHABETICAL = Menu.FIRST;
|
||||
private final VisibilityLoggerMixin mVisibilityLoggerMixin =
|
||||
new VisibilityLoggerMixin(getMetricsCategory());
|
||||
private VisibilityLoggerMixin mVisibilityLoggerMixin;
|
||||
|
||||
private boolean mSortedByTimezone;
|
||||
|
||||
@@ -144,12 +144,6 @@ public class ZonePicker extends ListFragment implements Instrumentable {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
mVisibilityLoggerMixin.onAttach(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.ZONE_PICKER;
|
||||
@@ -169,6 +163,13 @@ public class ZonePicker extends ListFragment implements Instrumentable {
|
||||
activity.setTitle(R.string.date_time_set_timezone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mVisibilityLoggerMixin = new VisibilityLoggerMixin(getMetricsCategory(),
|
||||
FeatureFactory.getFactory(getContext()).getMetricsFeatureProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
@@ -23,10 +23,10 @@ import android.provider.Settings;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.widget.Switch;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
/** Handles the logic for flipping the storage management toggle on a {@link SwitchBar}. */
|
||||
public class AutomaticStorageManagerSwitchBarController
|
||||
|
||||
@@ -398,8 +398,6 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
|
||||
controllers.add(new CameraLaserSensorPreferenceController(context));
|
||||
controllers.add(new WifiDisplayCertificationPreferenceController(context));
|
||||
controllers.add(new WifiVerboseLoggingPreferenceController(context));
|
||||
controllers.add(new WifiAggressiveHandoverPreferenceController(context));
|
||||
controllers.add(new WifiRoamScansPreferenceController(context));
|
||||
controllers.add(new MobileDataAlwaysOnPreferenceController(context));
|
||||
controllers.add(new TetheringHardwareAccelPreferenceController(context));
|
||||
controllers.add(new SelectUsbConfigPreferenceController(context, lifecycle));
|
||||
@@ -424,6 +422,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
|
||||
controllers.add(new ShowLayoutBoundsPreferenceController(context));
|
||||
controllers.add(new RtlLayoutPreferenceController(context));
|
||||
controllers.add(new WindowAnimationScalePreferenceController(context));
|
||||
controllers.add(new EmulateDisplayCutoutPreferenceController(context));
|
||||
controllers.add(new TransitionAnimationScalePreferenceController(context));
|
||||
controllers.add(new AnimatorDurationScalePreferenceController(context));
|
||||
controllers.add(new SecondaryDisplayPreferenceController(context));
|
||||
@@ -441,6 +440,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
|
||||
controllers.add(new ProfileGpuRenderingPreferenceController(context));
|
||||
controllers.add(new KeepActivitiesPreferenceController(context));
|
||||
controllers.add(new BackgroundProcessLimitPreferenceController(context));
|
||||
controllers.add(new ShowFirstCrashDialogPreferenceController(context));
|
||||
controllers.add(new AppsNotRespondingPreferenceController(context));
|
||||
controllers.add(new NotificationChannelWarningsPreferenceController(context));
|
||||
controllers.add(new AllowAppsOnExternalPreferenceController(context));
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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.development;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.om.IOverlayManager;
|
||||
import android.content.om.OverlayInfo;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.support.v7.preference.TwoStatePreference;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.development.DeveloperOptionsPreferenceController;
|
||||
|
||||
public class EmulateDisplayCutoutPreferenceController extends
|
||||
DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener,
|
||||
PreferenceControllerMixin {
|
||||
|
||||
private static final String EMULATION_OVERLAY = "com.android.internal.display.cutout.emulation";
|
||||
private static final String KEY = "display_cutout_emulation";
|
||||
|
||||
private final IOverlayManager mOverlayManager;
|
||||
private final boolean mAvailable;
|
||||
|
||||
private TwoStatePreference mPreference;
|
||||
|
||||
@VisibleForTesting
|
||||
EmulateDisplayCutoutPreferenceController(Context context, IOverlayManager overlayManager) {
|
||||
super(context);
|
||||
mOverlayManager = overlayManager;
|
||||
mAvailable = overlayManager != null && getEmulationOverlayInfo() != null;
|
||||
}
|
||||
|
||||
public EmulateDisplayCutoutPreferenceController(Context context) {
|
||||
this(context, IOverlayManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.OVERLAY_SERVICE)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return mAvailable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
setPreference((TwoStatePreference) screen.findPreference(getPreferenceKey()));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setPreference(TwoStatePreference preference) {
|
||||
mPreference = preference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
return writeEnabled((boolean) newValue);
|
||||
}
|
||||
|
||||
private boolean writeEnabled(boolean newValue) {
|
||||
OverlayInfo current = getEmulationOverlayInfo();
|
||||
if (current == null || current.isEnabled() == newValue) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return mOverlayManager.setEnabled(EMULATION_OVERLAY, newValue, UserHandle.USER_SYSTEM);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
OverlayInfo overlayInfo = getEmulationOverlayInfo();
|
||||
mPreference.setChecked(overlayInfo != null && overlayInfo.isEnabled());
|
||||
}
|
||||
|
||||
private OverlayInfo getEmulationOverlayInfo() {
|
||||
OverlayInfo overlayInfo = null;
|
||||
try {
|
||||
overlayInfo = mOverlayManager.getOverlayInfo(EMULATION_OVERLAY, UserHandle.USER_SYSTEM);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
return overlayInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeveloperOptionsSwitchEnabled() {
|
||||
mPreference.setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeveloperOptionsSwitchDisabled() {
|
||||
writeEnabled(false);
|
||||
mPreference.setChecked(false);
|
||||
mPreference.setEnabled(false);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
* 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.
|
||||
@@ -17,7 +17,7 @@
|
||||
package com.android.settings.development;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.provider.Settings;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v14.preference.SwitchPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
@@ -26,29 +26,34 @@ import android.support.v7.preference.PreferenceScreen;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.development.DeveloperOptionsPreferenceController;
|
||||
|
||||
public class WifiRoamScansPreferenceController extends
|
||||
public class ShowFirstCrashDialogPreferenceController extends
|
||||
DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener,
|
||||
PreferenceControllerMixin {
|
||||
|
||||
private static final String WIFI_ALLOW_SCAN_WITH_TRAFFIC_KEY = "wifi_allow_scan_with_traffic";
|
||||
private static final String SHOW_FIRST_CRASH_DIALOG_KEY = "show_first_crash_dialog";
|
||||
|
||||
@VisibleForTesting
|
||||
static final int SETTING_VALUE_ON = 1;
|
||||
@VisibleForTesting
|
||||
static final int SETTING_VALUE_OFF = 0;
|
||||
|
||||
private final WifiManager mWifiManager;
|
||||
private SwitchPreference mPreference;
|
||||
|
||||
public WifiRoamScansPreferenceController(Context context) {
|
||||
public ShowFirstCrashDialogPreferenceController(Context context) {
|
||||
super(context);
|
||||
|
||||
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return WIFI_ALLOW_SCAN_WITH_TRAFFIC_KEY;
|
||||
return SHOW_FIRST_CRASH_DIALOG_KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
// If the global setting is on, hide this preference since the global overrides
|
||||
// any user preference.
|
||||
return Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.SHOW_FIRST_CRASH_DIALOG, SETTING_VALUE_OFF) == SETTING_VALUE_OFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,14 +66,17 @@ public class WifiRoamScansPreferenceController extends
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
final boolean isEnabled = (Boolean) newValue;
|
||||
mWifiManager.setAllowScansWithTraffic(isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF);
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
|
||||
isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
final boolean enabled = mWifiManager.getAllowScansWithTraffic() > 0;
|
||||
mPreference.setChecked(enabled);
|
||||
final int mode = Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION, SETTING_VALUE_OFF);
|
||||
mPreference.setChecked(mode != SETTING_VALUE_OFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -78,7 +86,8 @@ public class WifiRoamScansPreferenceController extends
|
||||
|
||||
@Override
|
||||
protected void onDeveloperOptionsSwitchDisabled() {
|
||||
mWifiManager.setAllowScansWithTraffic(SETTING_VALUE_OFF);
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION, SETTING_VALUE_OFF);
|
||||
mPreference.setEnabled(false);
|
||||
mPreference.setChecked(false);
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.development;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v14.preference.SwitchPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.development.DeveloperOptionsPreferenceController;
|
||||
|
||||
public class WifiAggressiveHandoverPreferenceController extends
|
||||
DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener,
|
||||
PreferenceControllerMixin {
|
||||
|
||||
private static final String WIFI_AGGRESSIVE_HANDOVER_KEY = "wifi_aggressive_handover";
|
||||
|
||||
@VisibleForTesting
|
||||
static final int SETTING_VALUE_ON = 1;
|
||||
@VisibleForTesting
|
||||
static final int SETTING_VALUE_OFF = 0;
|
||||
|
||||
private final WifiManager mWifiManager;
|
||||
private SwitchPreference mPreference;
|
||||
|
||||
public WifiAggressiveHandoverPreferenceController(Context context) {
|
||||
super(context);
|
||||
|
||||
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return WIFI_AGGRESSIVE_HANDOVER_KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
|
||||
mPreference = (SwitchPreference) screen.findPreference(getPreferenceKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
boolean isEnabled = (Boolean) newValue;
|
||||
mWifiManager.enableAggressiveHandover(isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
boolean enabled = mWifiManager.getAggressiveHandover() > 0;
|
||||
mPreference.setChecked(enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeveloperOptionsSwitchEnabled() {
|
||||
mPreference.setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDeveloperOptionsSwitchDisabled() {
|
||||
mWifiManager.enableAggressiveHandover(SETTING_VALUE_OFF);
|
||||
mPreference.setChecked(false);
|
||||
mPreference.setEnabled(false);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.settings.development.qstile;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
import android.os.RemoteException;
|
||||
@@ -30,6 +31,7 @@ import android.view.IWindowManager;
|
||||
import android.view.ThreadedRenderer;
|
||||
import android.view.View;
|
||||
import android.view.WindowManagerGlobal;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.internal.app.LocalePicker;
|
||||
import com.android.settings.wrapper.IWindowManagerWrapper;
|
||||
@@ -145,12 +147,17 @@ public abstract class DevelopmentTiles extends TileService {
|
||||
public static class WindowTrace extends DevelopmentTiles {
|
||||
@VisibleForTesting
|
||||
IWindowManagerWrapper mWindowManager;
|
||||
@VisibleForTesting
|
||||
Toast mToast;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
mWindowManager = new IWindowManagerWrapper(WindowManagerGlobal
|
||||
.getWindowManagerService());
|
||||
Context context = getApplicationContext();
|
||||
CharSequence text = "Trace written to /data/misc/wmtrace/wm_trace.pb";
|
||||
mToast = Toast.makeText(context, text, Toast.LENGTH_LONG);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -171,6 +178,7 @@ public abstract class DevelopmentTiles extends TileService {
|
||||
mWindowManager.startWindowTrace();
|
||||
} else {
|
||||
mWindowManager.stopWindowTrace();
|
||||
mToast.show();
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not set window trace status." + e.toString());
|
||||
@@ -188,11 +196,16 @@ public abstract class DevelopmentTiles extends TileService {
|
||||
static final int SURFACE_FLINGER_LAYER_TRACE_STATUS_CODE = 1026;
|
||||
@VisibleForTesting
|
||||
IBinder mSurfaceFlinger;
|
||||
@VisibleForTesting
|
||||
Toast mToast;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger");
|
||||
Context context = getApplicationContext();
|
||||
CharSequence text = "Trace written to /data/misc/wmtrace/layers_trace.pb";
|
||||
mToast = Toast.makeText(context, text, Toast.LENGTH_LONG);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -230,6 +243,9 @@ public abstract class DevelopmentTiles extends TileService {
|
||||
data.writeInt(isEnabled ? 1 : 0);
|
||||
mSurfaceFlinger.transact(SURFACE_FLINGER_LAYER_TRACE_CONTROL_CODE,
|
||||
data, null, 0 /* flags */);
|
||||
if (!isEnabled){
|
||||
mToast.show();
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Could not set layer tracing." + e.toString());
|
||||
|
||||
@@ -34,11 +34,11 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
|
||||
@@ -25,12 +25,12 @@ import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.deletionhelper.ActivationWarningFragment;
|
||||
import com.android.settings.widget.MasterSwitchController;
|
||||
import com.android.settings.widget.MasterSwitchPreference;
|
||||
import com.android.settings.widget.SwitchWidgetController;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
|
||||
|
||||
@@ -38,11 +38,11 @@ import com.android.settings.Settings;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.manageapplications.ManageApplications;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.deviceinfo.PrivateVolumeSettings.SystemInfoFragment;
|
||||
import com.android.settings.deviceinfo.StorageItemPreference;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.deviceinfo.StorageMeasurement;
|
||||
import com.android.settingslib.deviceinfo.StorageVolumeProvider;
|
||||
|
||||
|
||||
@@ -27,11 +27,11 @@ import android.support.v7.preference.Preference;
|
||||
import com.android.internal.hardware.AmbientDisplayConfiguration;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.search.DatabaseIndexingUtils;
|
||||
import com.android.settings.search.InlineSwitchPayload;
|
||||
import com.android.settings.search.ResultPayload;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
public class AmbientDisplayNotificationsPreferenceController extends
|
||||
AbstractPreferenceController implements PreferenceControllerMixin,
|
||||
|
||||
@@ -23,13 +23,13 @@ import android.provider.SearchIndexableResource;
|
||||
import com.android.internal.hardware.AmbientDisplayConfiguration;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.gestures.DoubleTapScreenPreferenceController;
|
||||
import com.android.settings.gestures.PickupGesturePreferenceController;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -20,9 +20,9 @@ import android.support.v7.preference.TwoStatePreference;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.internal.view.RotationPolicy;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
|
||||
@@ -29,9 +29,9 @@ import android.text.TextUtils;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
import libcore.util.Objects;
|
||||
|
||||
|
||||
@@ -13,9 +13,11 @@
|
||||
*/
|
||||
package com.android.settings.display;
|
||||
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.util.Log;
|
||||
@@ -25,10 +27,9 @@ import com.android.settings.TimeoutListPreference;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
|
||||
|
||||
public class TimeoutPreferenceController extends AbstractPreferenceController implements
|
||||
PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
|
||||
|
||||
@@ -69,6 +70,13 @@ public class TimeoutPreferenceController extends AbstractPreferenceController im
|
||||
timeoutListPreference.removeUnusableTimeouts(maxTimeout, admin);
|
||||
}
|
||||
updateTimeoutPreferenceDescription(timeoutListPreference, currentTimeout);
|
||||
|
||||
EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(
|
||||
mContext, UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT,
|
||||
UserHandle.myUserId());
|
||||
if(admin != null) {
|
||||
timeoutListPreference.removeUnusableTimeouts(0/* disable all*/, admin);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -45,7 +45,7 @@ public class ManageDeviceAdminPreferenceController extends AbstractPreferenceCon
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
return mContext.getResources().getBoolean(R.bool.config_show_manage_device_admin);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -48,7 +48,6 @@ import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.widget.ActionButtonPreference;
|
||||
import com.android.settings.wrapper.DevicePolicyManagerWrapper;
|
||||
@@ -56,6 +55,7 @@ import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.applications.AppUtils;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnDestroy;
|
||||
|
||||
@@ -54,9 +54,10 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
|
||||
private final int mUid;
|
||||
@VisibleForTesting
|
||||
DevicePolicyManagerWrapper mDpm;
|
||||
@VisibleForTesting
|
||||
BatteryUtils mBatteryUtils;
|
||||
private Fragment mFragment;
|
||||
private String mTargetPackage;
|
||||
private boolean mIsPreOApp;
|
||||
private PowerWhitelistBackend mPowerWhitelistBackend;
|
||||
|
||||
public BackgroundActivityPreferenceController(Context context, Fragment fragment,
|
||||
@@ -77,7 +78,7 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
|
||||
mUid = uid;
|
||||
mFragment = fragment;
|
||||
mTargetPackage = packageName;
|
||||
mIsPreOApp = isLegacyApp(packageName);
|
||||
mBatteryUtils = BatteryUtils.getInstance(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,12 +110,7 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
|
||||
* activity for this package
|
||||
*/
|
||||
public void setUnchecked(Preference preference) {
|
||||
if (mIsPreOApp) {
|
||||
mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage,
|
||||
AppOpsManager.MODE_IGNORED);
|
||||
}
|
||||
mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage,
|
||||
AppOpsManager.MODE_IGNORED);
|
||||
mBatteryUtils.setForceAppStandby(mUid, mTargetPackage, AppOpsManager.MODE_IGNORED);
|
||||
((SwitchPreference) preference).setChecked(false);
|
||||
updateSummary(preference);
|
||||
}
|
||||
@@ -133,30 +129,11 @@ public class BackgroundActivityPreferenceController extends AbstractPreferenceCo
|
||||
dialogFragment.show(mFragment.getFragmentManager(), TAG);
|
||||
return false;
|
||||
}
|
||||
if (mIsPreOApp) {
|
||||
mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, mUid, mTargetPackage,
|
||||
AppOpsManager.MODE_ALLOWED);
|
||||
}
|
||||
mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mUid, mTargetPackage,
|
||||
AppOpsManager.MODE_ALLOWED);
|
||||
mBatteryUtils.setForceAppStandby(mUid, mTargetPackage, AppOpsManager.MODE_ALLOWED);
|
||||
updateSummary(preference);
|
||||
return true;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isLegacyApp(final String packageName) {
|
||||
try {
|
||||
ApplicationInfo info = mPackageManager.getApplicationInfo(packageName,
|
||||
PackageManager.GET_META_DATA);
|
||||
|
||||
return info.targetSdkVersion < Build.VERSION_CODES.O;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e(TAG, "Cannot find package: " + packageName, e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void updateSummary(Preference preference) {
|
||||
if (mPowerWhitelistBackend.isWhitelisted(mTargetPackage)) {
|
||||
|
||||
@@ -49,10 +49,10 @@ import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.core.FeatureFlags;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.fuelgauge.anomaly.Anomaly;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnDestroy;
|
||||
|
||||
@@ -398,6 +398,19 @@ public class BatteryUtils {
|
||||
return timeMs * 1000;
|
||||
}
|
||||
|
||||
public void setForceAppStandby(int uid, String packageName,
|
||||
int mode) {
|
||||
final boolean isPreOApp = isLegacyApp(packageName);
|
||||
if (isPreOApp) {
|
||||
// Control whether app could run in the background if it is pre O app
|
||||
mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, uid, packageName,
|
||||
mode);
|
||||
}
|
||||
// Control whether app could run jobs in the background
|
||||
mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, packageName,
|
||||
mode);
|
||||
}
|
||||
|
||||
public void initBatteryStatsHelper(BatteryStatsHelper statsHelper, Bundle bundle,
|
||||
UserManager userManager) {
|
||||
statsHelper.create(bundle);
|
||||
@@ -481,5 +494,18 @@ public class BatteryUtils {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean isLegacyApp(final String packageName) {
|
||||
try {
|
||||
ApplicationInfo info = mPackageManager.getApplicationInfo(packageName,
|
||||
PackageManager.GET_META_DATA);
|
||||
|
||||
return info.targetSdkVersion < Build.VERSION_CODES.O;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e(TAG, "Cannot find package: " + packageName, e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -362,6 +362,16 @@ public class FakeUid extends Uid {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCpuActiveTime() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] getCpuClusterTimes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] getCpuFreqTimes(int procState, int which) {
|
||||
return null;
|
||||
|
||||
@@ -47,7 +47,6 @@ import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.LayoutPreference;
|
||||
import com.android.settings.applications.manageapplications.ManageApplications;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.dashboard.SummaryLoader;
|
||||
import com.android.settings.display.AmbientDisplayPreferenceController;
|
||||
import com.android.settings.display.AutoBrightnessPreferenceController;
|
||||
@@ -61,6 +60,7 @@ import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -54,7 +54,6 @@ import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.LayoutPreference;
|
||||
import com.android.settings.applications.manageapplications.ManageApplications;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.dashboard.SummaryLoader;
|
||||
import com.android.settings.display.AmbientDisplayPreferenceController;
|
||||
import com.android.settings.display.AutoBrightnessPreferenceController;
|
||||
@@ -67,6 +66,7 @@ import com.android.settings.fuelgauge.anomaly.AnomalyLoader;
|
||||
import com.android.settings.fuelgauge.anomaly.AnomalySummaryPreferenceController;
|
||||
import com.android.settings.fuelgauge.anomaly.AnomalyUtils;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -20,9 +20,11 @@ package com.android.settings.fuelgauge;
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v14.preference.PreferenceFragment;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.applications.LayoutPreference;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
@@ -37,12 +39,21 @@ public class RestrictAppPreferenceController extends BasePreferenceController {
|
||||
|
||||
private AppOpsManager mAppOpsManager;
|
||||
private List<AppOpsManager.PackageOps> mPackageOps;
|
||||
private SettingsActivity mSettingsActivity;
|
||||
private PreferenceFragment mPreferenceFragment;
|
||||
|
||||
public RestrictAppPreferenceController(Context context) {
|
||||
super(context, KEY_RESTRICT_APP);
|
||||
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
|
||||
}
|
||||
|
||||
public RestrictAppPreferenceController(SettingsActivity settingsActivity,
|
||||
PreferenceFragment preferenceFragment) {
|
||||
this(settingsActivity.getApplicationContext());
|
||||
mSettingsActivity = settingsActivity;
|
||||
mPreferenceFragment = preferenceFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE;
|
||||
@@ -51,13 +62,27 @@ public class RestrictAppPreferenceController extends BasePreferenceController {
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
|
||||
mPackageOps = mAppOpsManager.getPackagesForOps(
|
||||
new int[]{AppOpsManager.OP_RUN_ANY_IN_BACKGROUND});
|
||||
final int num = mPackageOps != null ? mPackageOps.size() : 0;
|
||||
|
||||
// Enable the preference if some apps already been restricted, otherwise disable it
|
||||
preference.setEnabled(num > 0);
|
||||
preference.setSummary(
|
||||
mContext.getResources().getQuantityString(R.plurals.restricted_app_summary, num,
|
||||
num));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlePreferenceTreeClick(Preference preference) {
|
||||
if (getPreferenceKey().equals(preference.getKey())) {
|
||||
// start fragment
|
||||
RestrictedAppDetails.startRestrictedAppDetails(mSettingsActivity, mPreferenceFragment,
|
||||
mPackageOps);
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.handlePreferenceTreeClick(preference);
|
||||
}
|
||||
}
|
||||
|
||||
147
src/com/android/settings/fuelgauge/RestrictedAppDetails.java
Normal file
147
src/com/android/settings/fuelgauge/RestrictedAppDetails.java
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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.fuelgauge;
|
||||
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.support.v14.preference.PreferenceFragment;
|
||||
import android.support.v14.preference.SwitchPreference;
|
||||
import android.support.v7.preference.CheckBoxPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceGroup;
|
||||
import android.util.IconDrawableFactory;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.fuelgauge.anomaly.Anomaly;
|
||||
import com.android.settings.fuelgauge.anomaly.AnomalyDialogFragment;
|
||||
import com.android.settings.fuelgauge.anomaly.AnomalyPreference;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Fragment to show a list of anomaly apps, where user could handle these anomalies
|
||||
*/
|
||||
public class RestrictedAppDetails extends DashboardFragment {
|
||||
|
||||
public static final String TAG = "RestrictedAppDetails";
|
||||
|
||||
private static final String EXTRA_PACKAGE_OPS_LIST = "package_ops_list";
|
||||
private static final String KEY_PREF_RESTRICTED_APP_LIST = "restrict_app_list";
|
||||
|
||||
@VisibleForTesting
|
||||
List<AppOpsManager.PackageOps> mPackageOpsList;
|
||||
@VisibleForTesting
|
||||
IconDrawableFactory mIconDrawableFactory;
|
||||
@VisibleForTesting
|
||||
PreferenceGroup mRestrictedAppListGroup;
|
||||
@VisibleForTesting
|
||||
BatteryUtils mBatteryUtils;
|
||||
@VisibleForTesting
|
||||
PackageManager mPackageManager;
|
||||
|
||||
public static void startRestrictedAppDetails(SettingsActivity caller,
|
||||
PreferenceFragment fragment, List<AppOpsManager.PackageOps> packageOpsList) {
|
||||
Bundle args = new Bundle();
|
||||
args.putParcelableList(EXTRA_PACKAGE_OPS_LIST, packageOpsList);
|
||||
|
||||
caller.startPreferencePanelAsUser(fragment, RestrictedAppDetails.class.getName(), args,
|
||||
R.string.restricted_app_title, null /* titleText */,
|
||||
new UserHandle(UserHandle.myUserId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
final Context context = getContext();
|
||||
|
||||
mRestrictedAppListGroup = (PreferenceGroup) findPreference(KEY_PREF_RESTRICTED_APP_LIST);
|
||||
mPackageOpsList = getArguments().getParcelableArrayList(EXTRA_PACKAGE_OPS_LIST);
|
||||
mPackageManager = context.getPackageManager();
|
||||
mIconDrawableFactory = IconDrawableFactory.newInstance(context);
|
||||
mBatteryUtils = BatteryUtils.getInstance(context);
|
||||
|
||||
refreshUi();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(Preference preference) {
|
||||
|
||||
return super.onPreferenceTreeClick(preference);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.restricted_apps_detail;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.FUELGAUGE_RESTRICTED_APP_DETAILS;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void refreshUi() {
|
||||
mRestrictedAppListGroup.removeAll();
|
||||
final Context context = getPrefContext();
|
||||
|
||||
for (int i = 0, size = mPackageOpsList.size(); i < size; i++) {
|
||||
final CheckBoxPreference checkBoxPreference = new CheckBoxPreference(context);
|
||||
final AppOpsManager.PackageOps packageOps = mPackageOpsList.get(i);
|
||||
try {
|
||||
final ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(
|
||||
packageOps.getPackageName(), 0 /* flags */);
|
||||
checkBoxPreference.setChecked(true);
|
||||
checkBoxPreference.setTitle(mPackageManager.getApplicationLabel(applicationInfo));
|
||||
checkBoxPreference.setKey(packageOps.getPackageName());
|
||||
checkBoxPreference.setOnPreferenceChangeListener((pref, value) -> {
|
||||
// change the toggle
|
||||
final int mode = (Boolean) value ? AppOpsManager.MODE_IGNORED
|
||||
: AppOpsManager.MODE_ALLOWED;
|
||||
final String packageName = pref.getKey();
|
||||
final int uid = mBatteryUtils.getPackageUid(packageName);
|
||||
mBatteryUtils.setForceAppStandby(uid, packageName, mode);
|
||||
return true;
|
||||
});
|
||||
mRestrictedAppListGroup.addPreference(checkBoxPreference);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,9 +19,11 @@ package com.android.settings.fuelgauge;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.support.v14.preference.PreferenceFragment;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
@@ -63,14 +65,20 @@ public class SmartBatterySettings extends DashboardFragment {
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
return buildPreferenceControllers(context);
|
||||
return buildPreferenceControllers(context, (SettingsActivity) getActivity(), this);
|
||||
}
|
||||
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(
|
||||
Context context) {
|
||||
Context context, SettingsActivity settingsActivity, PreferenceFragment fragment) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new SmartBatteryPreferenceController(context));
|
||||
controllers.add(new RestrictAppPreferenceController(context));
|
||||
if (settingsActivity != null && fragment != null) {
|
||||
controllers.add(
|
||||
new RestrictAppPreferenceController(settingsActivity, fragment));
|
||||
} else {
|
||||
controllers.add(new RestrictAppPreferenceController(context));
|
||||
}
|
||||
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@@ -92,7 +100,7 @@ public class SmartBatterySettings extends DashboardFragment {
|
||||
@Override
|
||||
public List<AbstractPreferenceController> getPreferenceControllers(
|
||||
Context context) {
|
||||
return buildPreferenceControllers(context);
|
||||
return buildPreferenceControllers(context, null, null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import android.util.SparseIntArray;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.internal.os.BatteryStatsHelper;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.fuelgauge.anomaly.action.AnomalyAction;
|
||||
import com.android.settings.fuelgauge.anomaly.action.ForceStopAction;
|
||||
import com.android.settings.fuelgauge.anomaly.action.LocationCheckAction;
|
||||
@@ -33,6 +32,7 @@ import com.android.settings.fuelgauge.anomaly.checker.AnomalyDetector;
|
||||
import com.android.settings.fuelgauge.anomaly.checker.BluetoothScanAnomalyDetector;
|
||||
import com.android.settings.fuelgauge.anomaly.checker.WakeLockAnomalyDetector;
|
||||
import com.android.settings.fuelgauge.anomaly.checker.WakeupAlarmAnomalyDetector;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -20,9 +20,9 @@ import android.content.Context;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.fuelgauge.anomaly.Anomaly;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
/**
|
||||
* Abstract class for anomaly action, which is triggered if we need to handle the anomaly
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.fuelgauge.batterytip;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settings.fuelgauge.anomaly.Anomaly;
|
||||
|
||||
/**
|
||||
* Database controls the anomaly logging(e.g. packageName, anomalyType and time)
|
||||
*/
|
||||
public class AnomalyDatabaseHelper extends SQLiteOpenHelper {
|
||||
private static final String TAG = "BatteryDatabaseHelper";
|
||||
|
||||
private static final String DATABASE_NAME = "battery_settings.db";
|
||||
private static final int DATABASE_VERSION = 1;
|
||||
|
||||
public interface Tables {
|
||||
String TABLE_ANOMALY = "anomaly";
|
||||
}
|
||||
|
||||
public interface AnomalyColumns {
|
||||
/**
|
||||
* The package name of the anomaly app
|
||||
*/
|
||||
String PACKAGE_NAME = "package_name";
|
||||
/**
|
||||
* The type of the anomaly app
|
||||
* @see Anomaly.AnomalyType
|
||||
*/
|
||||
String ANOMALY_TYPE = "anomaly_type";
|
||||
/**
|
||||
* The time when anomaly happens
|
||||
*/
|
||||
String TIME_STAMP_MS = "time_stamp_ms";
|
||||
}
|
||||
|
||||
private static final String CREATE_ANOMALY_TABLE =
|
||||
"CREATE TABLE " + Tables.TABLE_ANOMALY +
|
||||
"(" +
|
||||
AnomalyColumns.PACKAGE_NAME +
|
||||
" TEXT, " +
|
||||
AnomalyColumns.ANOMALY_TYPE +
|
||||
" INTEGER, " +
|
||||
AnomalyColumns.TIME_STAMP_MS +
|
||||
" INTEGER)";
|
||||
|
||||
private static AnomalyDatabaseHelper sSingleton;
|
||||
|
||||
public static synchronized AnomalyDatabaseHelper getInstance(Context context) {
|
||||
if (sSingleton == null) {
|
||||
sSingleton = new AnomalyDatabaseHelper(context.getApplicationContext());
|
||||
}
|
||||
return sSingleton;
|
||||
}
|
||||
|
||||
private AnomalyDatabaseHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
bootstrapDB(db);
|
||||
}
|
||||
|
||||
private void bootstrapDB(SQLiteDatabase db) {
|
||||
db.execSQL(CREATE_ANOMALY_TABLE);
|
||||
Log.i(TAG, "Bootstrapped database");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if (oldVersion < DATABASE_VERSION) {
|
||||
Log.w(TAG, "Detected schema version '" + oldVersion + "'. " +
|
||||
"Index needs to be rebuilt for schema version '" + newVersion + "'.");
|
||||
// We need to drop the tables and recreate them
|
||||
reconstruct(db);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
Log.w(TAG, "Detected schema version '" + oldVersion + "'. " +
|
||||
"Index needs to be rebuilt for schema version '" + newVersion + "'.");
|
||||
// We need to drop the tables and recreate them
|
||||
reconstruct(db);
|
||||
}
|
||||
|
||||
public void reconstruct(SQLiteDatabase db) {
|
||||
dropTables(db);
|
||||
bootstrapDB(db);
|
||||
}
|
||||
|
||||
private void dropTables(SQLiteDatabase db) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_ANOMALY);
|
||||
}
|
||||
}
|
||||
101
src/com/android/settings/fuelgauge/batterytip/AppInfo.java
Normal file
101
src/com/android/settings/fuelgauge/batterytip/AppInfo.java
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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.fuelgauge.batterytip;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.fuelgauge.anomaly.Anomaly;
|
||||
|
||||
/**
|
||||
* Model class stores app info(e.g. package name, type..) that used in battery tip
|
||||
*/
|
||||
public class AppInfo implements Comparable<AppInfo>, Parcelable {
|
||||
public final String packageName;
|
||||
/**
|
||||
* Anomaly type of the app
|
||||
* @see Anomaly.AnomalyType
|
||||
*/
|
||||
public final int anomalyType;
|
||||
public final long screenOnTimeMs;
|
||||
|
||||
private AppInfo(AppInfo.Builder builder) {
|
||||
packageName = builder.mPackageName;
|
||||
anomalyType = builder.mAnomalyType;
|
||||
screenOnTimeMs = builder.mScreenOnTimeMs;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
AppInfo(Parcel in) {
|
||||
packageName = in.readString();
|
||||
anomalyType = in.readInt();
|
||||
screenOnTimeMs = in.readLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(AppInfo o) {
|
||||
return Long.compare(screenOnTimeMs, o.screenOnTimeMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(packageName);
|
||||
dest.writeInt(anomalyType);
|
||||
dest.writeLong(screenOnTimeMs);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
|
||||
public AppInfo createFromParcel(Parcel in) {
|
||||
return new AppInfo(in);
|
||||
}
|
||||
|
||||
public AppInfo[] newArray(int size) {
|
||||
return new AppInfo[size];
|
||||
}
|
||||
};
|
||||
|
||||
public static final class Builder {
|
||||
private int mAnomalyType;
|
||||
private String mPackageName;
|
||||
private long mScreenOnTimeMs;
|
||||
|
||||
public Builder setAnomalyType(int type) {
|
||||
mAnomalyType = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPackageName(String packageName) {
|
||||
mPackageName = packageName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setScreenOnTimeMs(long screenOnTimeMs) {
|
||||
mScreenOnTimeMs = screenOnTimeMs;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AppInfo build() {
|
||||
return new AppInfo(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.fuelgauge.batterytip;
|
||||
|
||||
import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
|
||||
.PACKAGE_NAME;
|
||||
import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
|
||||
.ANOMALY_TYPE;
|
||||
import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
|
||||
.TIME_STAMP_MS;
|
||||
import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.Tables.TABLE_ANOMALY;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Database manager for battery data. Now it only contains anomaly data stored in {@link AppInfo}.
|
||||
*/
|
||||
public class BatteryDatabaseManager {
|
||||
private final AnomalyDatabaseHelper mDatabaseHelper;
|
||||
|
||||
public BatteryDatabaseManager(Context context) {
|
||||
mDatabaseHelper = AnomalyDatabaseHelper.getInstance(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an anomaly log to database.
|
||||
*
|
||||
* @param packageName the package name of the app
|
||||
* @param type the type of the anomaly
|
||||
* @param timestampMs the time when it is happened
|
||||
*/
|
||||
public void insertAnomaly(String packageName, int type, long timestampMs) {
|
||||
try (SQLiteDatabase db = mDatabaseHelper.getWritableDatabase()) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(PACKAGE_NAME, packageName);
|
||||
values.put(ANOMALY_TYPE, type);
|
||||
values.put(TIME_STAMP_MS, timestampMs);
|
||||
|
||||
db.insert(TABLE_ANOMALY, null, values);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Query all the anomalies that happened after {@code timestampMs}.
|
||||
*/
|
||||
public List<AppInfo> queryAllAnomaliesAfter(long timestampMs) {
|
||||
final List<AppInfo> appInfos = new ArrayList<>();
|
||||
try (SQLiteDatabase db = mDatabaseHelper.getReadableDatabase()) {
|
||||
final String[] projection = {PACKAGE_NAME, ANOMALY_TYPE};
|
||||
final String orderBy = AnomalyDatabaseHelper.AnomalyColumns.TIME_STAMP_MS + " DESC";
|
||||
|
||||
try (Cursor cursor = db.query(TABLE_ANOMALY, projection, TIME_STAMP_MS + " > ?",
|
||||
new String[]{String.valueOf(timestampMs)}, null, null, orderBy)) {
|
||||
while (cursor.moveToNext()) {
|
||||
AppInfo appInfo = new AppInfo.Builder()
|
||||
.setPackageName(cursor.getString(cursor.getColumnIndex(PACKAGE_NAME)))
|
||||
.setAnomalyType(cursor.getInt(cursor.getColumnIndex(ANOMALY_TYPE)))
|
||||
.build();
|
||||
appInfos.add(appInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return appInfos;
|
||||
}
|
||||
|
||||
public void deleteAllAnomaliesBeforeTimeStamp(long timestampMs) {
|
||||
try (SQLiteDatabase db = mDatabaseHelper.getWritableDatabase()) {
|
||||
db.delete(TABLE_ANOMALY, TIME_STAMP_MS + " < ?",
|
||||
new String[]{String.valueOf(timestampMs)});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import android.view.LayoutInflater;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController.BatteryTipListener;
|
||||
import com.android.settings.fuelgauge.batterytip.actions.BatteryTipAction;
|
||||
@@ -78,7 +79,8 @@ public class BatteryTipDialogFragment extends InstrumentedDialogFragment impleme
|
||||
|
||||
return new AlertDialog.Builder(context)
|
||||
.setMessage(getString(R.string.battery_tip_dialog_message,
|
||||
highUsageTip.getScreenTimeMs()))
|
||||
Utils.formatElapsedTime(context, highUsageTip.getScreenTimeMs(),
|
||||
false /* withSeconds */)))
|
||||
.setView(view)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.create();
|
||||
|
||||
@@ -39,7 +39,7 @@ public class HighUsageAdapter extends RecyclerView.Adapter<HighUsageAdapter.View
|
||||
private final Context mContext;
|
||||
private final IconDrawableFactory mIconDrawableFactory;
|
||||
private final PackageManager mPackageManager;
|
||||
private final List<HighUsageApp> mHighUsageAppList;
|
||||
private final List<AppInfo> mHighUsageAppList;
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
public View view;
|
||||
@@ -56,7 +56,7 @@ public class HighUsageAdapter extends RecyclerView.Adapter<HighUsageAdapter.View
|
||||
}
|
||||
}
|
||||
|
||||
public HighUsageAdapter(Context context, List<HighUsageApp> highUsageAppList) {
|
||||
public HighUsageAdapter(Context context, List<AppInfo> highUsageAppList) {
|
||||
mContext = context;
|
||||
mHighUsageAppList = highUsageAppList;
|
||||
mIconDrawableFactory = IconDrawableFactory.newInstance(context);
|
||||
@@ -72,7 +72,7 @@ public class HighUsageAdapter extends RecyclerView.Adapter<HighUsageAdapter.View
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
final HighUsageApp app = mHighUsageAppList.get(position);
|
||||
final AppInfo app = mHighUsageAppList.get(position);
|
||||
holder.appIcon.setImageDrawable(
|
||||
Utils.getBadgedIcon(mIconDrawableFactory, mPackageManager, app.packageName,
|
||||
UserHandle.myUserId()));
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* 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.fuelgauge.batterytip;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Class representing app with high screen usage
|
||||
*/
|
||||
public class HighUsageApp implements Comparable<HighUsageApp>, Parcelable {
|
||||
public final String packageName;
|
||||
public final long screenOnTimeMs;
|
||||
|
||||
public HighUsageApp(String packageName, long screenOnTimeMs) {
|
||||
this.packageName = packageName;
|
||||
this.screenOnTimeMs = screenOnTimeMs;
|
||||
}
|
||||
|
||||
private HighUsageApp(Parcel in) {
|
||||
packageName = in.readString();
|
||||
screenOnTimeMs = in.readLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(HighUsageApp o) {
|
||||
return Long.compare(screenOnTimeMs, o.screenOnTimeMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(packageName);
|
||||
dest.writeLong(screenOnTimeMs);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
|
||||
public HighUsageApp createFromParcel(Parcel in) {
|
||||
return new HighUsageApp(in);
|
||||
}
|
||||
|
||||
public HighUsageApp[] newArray(int size) {
|
||||
return new HighUsageApp[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -18,7 +18,7 @@ package com.android.settings.fuelgauge.batterytip.actions;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
/**
|
||||
* Abstract class for battery tip action, which is triggered if we need to handle the battery tip
|
||||
|
||||
@@ -22,8 +22,8 @@ import android.support.v14.preference.PreferenceFragment;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settings.fuelgauge.SmartBatterySettings;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
|
||||
public class SmartBatteryAction extends BatteryTipAction {
|
||||
private SettingsActivity mSettingsActivity;
|
||||
|
||||
@@ -23,13 +23,11 @@ import android.text.format.DateUtils;
|
||||
|
||||
import com.android.internal.os.BatterySipper;
|
||||
import com.android.internal.os.BatteryStatsHelper;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.fuelgauge.BatteryUtils;
|
||||
import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy;
|
||||
import com.android.settings.fuelgauge.batterytip.HighUsageApp;
|
||||
import com.android.settings.fuelgauge.batterytip.AppInfo;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.SummaryTip;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -42,7 +40,7 @@ import java.util.List;
|
||||
public class HighUsageDetector implements BatteryTipDetector {
|
||||
private BatteryTipPolicy mPolicy;
|
||||
private BatteryStatsHelper mBatteryStatsHelper;
|
||||
private List<HighUsageApp> mHighUsageAppList;
|
||||
private List<AppInfo> mHighUsageAppList;
|
||||
private Context mContext;
|
||||
@VisibleForTesting
|
||||
BatteryUtils mBatteryUtils;
|
||||
@@ -68,9 +66,10 @@ public class HighUsageDetector implements BatteryTipDetector {
|
||||
final long foregroundTimeMs = mBatteryUtils.getProcessTimeMs(
|
||||
BatteryUtils.StatusType.FOREGROUND, batterySipper.uidObj,
|
||||
BatteryStats.STATS_SINCE_CHARGED);
|
||||
mHighUsageAppList.add(new HighUsageApp(
|
||||
mBatteryUtils.getPackageName(batterySipper.getUid()),
|
||||
foregroundTimeMs));
|
||||
mHighUsageAppList.add(new AppInfo.Builder()
|
||||
.setPackageName(mBatteryUtils.getPackageName(batterySipper.getUid()))
|
||||
.setScreenOnTimeMs(foregroundTimeMs)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.fuelgauge.batterytip.HighUsageApp;
|
||||
import com.android.settings.fuelgauge.batterytip.AppInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -34,9 +34,9 @@ public class HighUsageTip extends BatteryTip {
|
||||
|
||||
private final long mScreenTimeMs;
|
||||
@VisibleForTesting
|
||||
final List<HighUsageApp> mHighUsageAppList;
|
||||
final List<AppInfo> mHighUsageAppList;
|
||||
|
||||
public HighUsageTip(long screenTimeMs, List<HighUsageApp> appList) {
|
||||
public HighUsageTip(long screenTimeMs, List<AppInfo> appList) {
|
||||
super(TipType.HIGH_DEVICE_USAGE, appList.isEmpty() ? StateType.INVISIBLE : StateType.NEW,
|
||||
true /* showDialog */);
|
||||
mScreenTimeMs = screenTimeMs;
|
||||
@@ -47,7 +47,7 @@ public class HighUsageTip extends BatteryTip {
|
||||
HighUsageTip(Parcel in) {
|
||||
super(in);
|
||||
mScreenTimeMs = in.readLong();
|
||||
mHighUsageAppList = in.createTypedArrayList(HighUsageApp.CREATOR);
|
||||
mHighUsageAppList = in.createTypedArrayList(AppInfo.CREATOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,7 +82,7 @@ public class HighUsageTip extends BatteryTip {
|
||||
return mScreenTimeMs;
|
||||
}
|
||||
|
||||
public List<HighUsageApp> getHighUsageAppList() {
|
||||
public List<AppInfo> getHighUsageAppList() {
|
||||
return mHighUsageAppList;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user