Merge "Make fallback home a bit more graceful." into nyc-dev
diff --git a/res/layout/app_domains_dialog.xml b/res/layout/app_domains_dialog.xml
index c00bff0..f9c6b64 100644
--- a/res/layout/app_domains_dialog.xml
+++ b/res/layout/app_domains_dialog.xml
@@ -26,6 +26,7 @@
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:divider="@null"
android:scrollbarStyle="insideOverlay" />
</FrameLayout>
diff --git a/res/layout/app_domains_item.xml b/res/layout/app_domains_item.xml
index 90fc0e4..e2ccbd3 100644
--- a/res/layout/app_domains_item.xml
+++ b/res/layout/app_domains_item.xml
@@ -22,4 +22,5 @@
android:paddingStart="4dp"
android:paddingEnd="4dp"
android:paddingTop="16dp"
+ android:divider="@null"
/>
diff --git a/res/layout/encryption_interstitial.xml b/res/layout/encryption_interstitial.xml
deleted file mode 100644
index 162ad0e..0000000
--- a/res/layout/encryption_interstitial.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- ~ Copyright (C) 2014 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:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingStart="?attr/side_margin"
- android:paddingEnd="?attr/side_margin">
-
- <TextView
- android:id="@+id/encryption_message"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
- android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <RadioGroup
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
- android:layout_marginEnd="?android:attr/listPreferredItemPaddingEnd"
- android:checkedButton="@+id/encrypt_require_password">
-
- <RadioButton
- android:id="@+id/encrypt_require_password"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp" />
-
- <RadioButton
- android:id="@+id/encrypt_dont_require_password"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp" />
-
- </RadioGroup>
-
-</LinearLayout>
diff --git a/res/layout/encryption_interstitial_header.xml b/res/layout/encryption_interstitial_header.xml
new file mode 100644
index 0000000..8d36432
--- /dev/null
+++ b/res/layout/encryption_interstitial_header.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:minHeight="56dp"
+ android:paddingTop="16dp"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:paddingBottom="16dp"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
diff --git a/res/layout/notification_log_row.xml b/res/layout/notification_log_row.xml
index d7f57c6..e76835e 100644
--- a/res/layout/notification_log_row.xml
+++ b/res/layout/notification_log_row.xml
@@ -27,11 +27,11 @@
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="@*android:dimen/status_bar_icon_size"
- android:layout_marginBottom="4dp"
+ android:layout_marginBottom="6dp"
>
<ImageView
- android:id="@android:id/icon"
+ android:id="@+id/icon"
android:layout_width="@*android:dimen/status_bar_icon_size"
android:layout_height="@*android:dimen/status_bar_icon_size"
android:layout_centerVertical="true"
@@ -40,17 +40,18 @@
android:layout_marginEnd="8dp"
android:contentDescription="@null"
android:adjustViewBounds="true"
+ android:tint="?android:attr/textColorPrimary"
android:maxHeight="@*android:dimen/status_bar_icon_size"
android:maxWidth="@*android:dimen/status_bar_icon_size"
android:scaleType="fitCenter" />
<TextView
- android:id="@android:id/title"
+ android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toStartOf="@+id/timestamp"
- android:layout_toEndOf="@android:id/icon"
+ android:layout_toEndOf="@id/icon"
android:ellipsize="end"
android:singleLine="true"
android:textColor="?android:attr/textColorPrimary"
@@ -75,24 +76,12 @@
/>
</RelativeLayout>
- <TextView
- android:id="@+id/extra"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_marginStart="30dp"
- android:ellipsize="end"
- android:singleLine="true"
- android:textColor="?android:attr/textColorPrimary"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textAlignment="viewStart"
- />
-
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@*android:dimen/status_bar_icon_size"
android:orientation="horizontal"
android:layout_marginStart="30dp"
+ android:layout_marginBottom="6dp"
>
<ImageView
@@ -120,4 +109,19 @@
/>
</LinearLayout>
+
+ <TextView
+ android:id="@+id/extra"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_marginStart="30dp"
+ android:layout_marginBottom="6dp"
+ android:singleLine="false"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="10sp"
+ android:fontFamily="monospace"
+ android:textAlignment="viewStart"
+ />
+
</LinearLayout>
diff --git a/res/layout/preference_wallpaper_type b/res/layout/preference_wallpaper_type
index 48bfffd..ee1fd30 100644
--- a/res/layout/preference_wallpaper_type
+++ b/res/layout/preference_wallpaper_type
@@ -16,7 +16,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
diff --git a/res/layout/preview_seek_bar_view_pager.xml b/res/layout/preview_seek_bar_view_pager.xml
index 4badca4..d16a356 100644
--- a/res/layout/preview_seek_bar_view_pager.xml
+++ b/res/layout/preview_seek_bar_view_pager.xml
@@ -45,7 +45,7 @@
android:gravity="center"
android:text="@string/screen_zoom_preview_title"
android:textAppearance="@android:style/TextAppearance.Material.Widget.ActionBar.Title"
- android:textColor="?android:attr/textColorPrimaryInverse"
+ android:textColor="@color/seek_bar_preference_preview_text"
android:elevation="2dp"/>
</RelativeLayout>
diff --git a/res/layout/setup_encryption_interstitial.xml b/res/layout/setup_encryption_interstitial.xml
deleted file mode 100644
index 8a36e30..0000000
--- a/res/layout/setup_encryption_interstitial.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License
--->
-
-<com.android.setupwizardlib.SetupWizardLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:settings="http://schemas.android.com/apk/res-auto"
- android:id="@+id/setup_wizard_layout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- settings:suwBackgroundTile="@drawable/setup_illustration_tile"
- settings:suwHeaderText="@string/encryption_interstitial_header"
- settings:suwIllustrationHorizontalTile="@drawable/setup_illustration_horizontal_tile"
- settings:suwIllustrationImage="@drawable/setup_illustration_lock_screen">
-
- <LinearLayout
- style="@style/SuwContentFrame"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/encryption_message"
- style="@style/SuwDescription"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- <RadioGroup
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="16dp"
- android:checkedButton="@+id/encrypt_require_password">
-
- <RadioButton
- android:id="@+id/encrypt_require_password"
- style="@style/SuwRadioButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- <RadioButton
- android:id="@+id/encrypt_dont_require_password"
- style="@style/SuwRadioButton"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
- </RadioGroup>
-
- </LinearLayout>
-
-</com.android.setupwizardlib.SetupWizardLayout>
diff --git a/res/layout/setup_encryption_interstitial_header.xml b/res/layout/setup_encryption_interstitial_header.xml
new file mode 100644
index 0000000..82344bb
--- /dev/null
+++ b/res/layout/setup_encryption_interstitial_header.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:minHeight="56dp"
+ android:paddingBottom="@dimen/suw_description_margin_bottom"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:paddingTop="@dimen/suw_description_margin_top"
+ android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
+ android:textAppearance="?android:attr/textAppearanceListItem" />
diff --git a/res/layout/suw_item_link_description.xml b/res/layout/suw_item_link_description.xml
new file mode 100644
index 0000000..5396de1e
--- /dev/null
+++ b/res/layout/suw_item_link_description.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ style="@style/SuwItemContainer"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:paddingTop="@dimen/suw_description_margin_top"
+ android:paddingBottom="@dimen/suw_description_margin_bottom_lists">
+
+ <FrameLayout
+ android:id="@+id/suw_items_icon_container"
+ android:layout_width="@dimen/suw_items_icon_container_width"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:gravity="start">
+
+ <ImageView
+ android:id="@+id/suw_items_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ tools:ignore="ContentDescription" />
+
+ </FrameLayout>
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <com.android.settings.widget.LinkTextView
+ android:id="@+id/suw_items_title"
+ style="@style/SuwItemTitle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="start"
+ android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
+ android:textAlignment="viewStart"
+ android:textAppearance="@style/TextAppearance.SuwDescription"
+ tools:ignore="UnusedAttribute" />
+
+ <com.android.settings.widget.LinkTextView
+ android:id="@+id/suw_items_summary"
+ style="@style/SuwItemSummary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="start"
+ android:textAlignment="viewStart"
+ android:visibility="gone"
+ tools:ignore="UnusedAttribute" />
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index fd21db1..3b9e712 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -740,9 +740,7 @@
<!-- Introduction title shown in fingerprint enrollment to introduce the fingerprint feature[CHAR LIMIT=29] -->
<string name="security_settings_fingerprint_enroll_introduction_title">Unlock with fingerprint</string>
<!-- Introduction detail message shown in fingerprint enrollment dialog [CHAR LIMIT=NONE]-->
- <string name="security_settings_fingerprint_enroll_introduction_message">Just touch the fingerprint sensor to unlock your phone, authorize purchases, or sign in to apps. \n\n Be careful whose fingerprints you add - any fingerprints added will be able to do these things.</string>
- <!-- Introduction detail message shown in fingerprint enrollment dialog to warn the user [CHAR LIMIT=NONE]-->
- <string name="security_settings_fingerprint_enroll_introduction_message_warning">Note: Your fingerprint may be less secure than a strong pattern or PIN. <annotation id="url">Learn more</annotation></string>
+ <string name="security_settings_fingerprint_enroll_introduction_message">Just touch the fingerprint sensor to unlock your phone, authorize purchases, or sign in to apps. Be careful whose fingerprints you add. Even one added print can do any of these things.\n\nNote: Your fingerprint may be less secure than a strong pattern or PIN. <annotation id="url">Learn more</annotation></string>
<!-- Button text to cancel enrollment from the introduction [CHAR LIMIT=22] -->
<string name="security_settings_fingerprint_enroll_introduction_cancel">Cancel</string>
<!-- Button text to continue to the next screen from the introduction [CHAR LIMIT=22] -->
@@ -990,6 +988,9 @@
<!-- Title for security picker to choose the unlock method: None/Pattern/PIN/Password [CHAR LIMIT=22] -->
<string name="lock_settings_picker_title">Choose screen lock</string>
+ <!-- Title for security picker to choose the profile unlock method: None/Pattern/PIN/Password [CHAR LIMIT=22] -->
+ <string name="lock_settings_picker_title_profile">Choose profile screen lock</string>
+
<!-- Title for security picker in setup wizard to choose the unlock method: None/Pattern/PIN/Password [CHAR LIMIT=22] -->
<string name="setup_lock_settings_picker_title">Protect your phone</string>
@@ -1010,6 +1011,10 @@
<!-- Title for PreferenceScreen to launch picker for security method when there is none [CHAR LIMIT=22] -->
<string name="unlock_set_unlock_launch_picker_title">Screen lock</string>
+ <!-- Profile Security lock settings --><skip />
+ <!-- Title for PreferenceScreen to launch picker for security method for the managed profile when there is none [CHAR LIMIT=22] -->
+ <string name="unlock_set_unlock_launch_picker_title_profile">Profile screen lock</string>
+
<!-- Title for PreferenceScreen to change security method: None/Pattern/PIN/Password [CHAR LIMIT=22] -->
<string name="unlock_set_unlock_launch_picker_change_title">Change lock screen</string>
@@ -3122,6 +3127,8 @@
<string name="lockpattern_settings_enable_summary">Must draw pattern to unlock screen</string>
<!-- Security & location settings screen, setting check box title. This setting controls whether a visible green line is drawn as the user moves his finger around while drawing the unlock pattern. If checked, this line is drawn. If unchecked, there is nothing drawn so the user does not reveal his pattern while he unlocks the phone.-->
<string name="lockpattern_settings_enable_visible_pattern_title">Make pattern visible</string>
+ <!-- Security & location settings screen, setting check box title. This setting controls whether a visible green line is drawn as the user moves his finger around while drawing the profile unlock pattern. If checked, this line is drawn. If unchecked, there is nothing drawn so the user does not reveal his pattern while he unlocks the profile.-->
+ <string name="lockpattern_settings_enable_visible_pattern_title_profile">Make profile pattern visible</string>
<!-- Security & location settings screen, setting check box title. This setting controls whether tactile feedback will be produced when the user draws the pattern.-->
<string name="lockpattern_settings_enable_tactile_feedback_title">Vibrate on tap</string>
<!-- Security & location settings screen, setting check box title. This controls whether the device locks immediately when the power button is pressed. [CHAR LIMIT=28]-->
@@ -3148,15 +3155,19 @@
<!-- Security & location settings screen, title when changing or confirming the work profile lock -->
<string name="lock_settings_profile_screen_lock_title">Work profile screen lock</string>
<!-- Security & location settings screen, setting option name to unify work and personal locks -->
- <string name="lock_settings_profile_unification_title">Use same screen lock</string>
+ <string name="lock_settings_profile_unification_title">Use the same lock</string>
<!-- Security & location settings screen, setting option explanation to unify work and personal locks -->
- <string name="lock_settings_profile_unification_summary">Change primary profile to match work profile</string>
+ <string name="lock_settings_profile_unification_summary">Change device screen lock to match work profile?</string>
<!-- Security & location settings screen, title of the dialog asking if the user wants to unify work and personal locks -->
<string name="lock_settings_profile_unification_dialog_title">Use the same screen lock?</string>
<!-- Security & location settings screen, explanation in the dialog asking if the user wants to unify work and personal locks -->
<string name="lock_settings_profile_unification_dialog_body">You can use this lock for your device but it will include all screen lock related policies set by your IT admin on the work profile.\nDo you want to use the same screen lock for your device?</string>
+ <!-- Security & location settings screen, explanation in the dialog asking if the user wants to create a new lock for personal and work as the current work lock is not enough for the device. -->
+ <string name="lock_settings_profile_unification_dialog_uncompliant_body">Your work screen lock doesn\'t meet your organization\'s security requirements.\nYou can set a new screen lock for both your device and your work profile, but any work screen lock policies will apply to your device screen lock as well.</string>
+ <!-- Security & location settings screen, confirmation button of the dialog asking if the user wants to create a new lock for both personal and work profiles. -->
+ <string name="lock_settings_profile_unification_dialog_uncompliant_confirm">Change lock</string>
<!-- Security & location settings screen, summary of the item that changes your work profile lock when it is unified with the personal lock -->
- <string name="lock_settings_profile_unified_summary">Same as your device lock</string>
+ <string name="lock_settings_profile_unified_summary">Same as device screen lock</string>
<!-- Applications Settings --> <skip />
<!-- Applications settings screen, setting option name for the user to go to the screen to manage installed applications -->
@@ -3825,7 +3836,7 @@
<!-- Summary for the preference screen to enable the global geture that turns on accessibility (off state). [CHAR LIMIT=35] -->
<string name="accessibility_global_gesture_preference_summary_off">Off</string>
<!-- Description for the preference screen to enable the global geture taht turns on accessibility. [CHAR LIMIT=none] -->
- <string name="accessibility_global_gesture_preference_description">When this feature is turned on, you can quickly activate accessibility features in two steps:\n\nStep 1: Press and hold the power button until you hear a sound or feel a vibration.\n\nStep 2: Tap & hold two fingers until you hear audio confirmation.\n\nIf the device has multiple users, using this shortcut on the lock screen temporarily enables accessibility until the device is unlocked.</string>
+ <string name="accessibility_global_gesture_preference_description">When this feature is turned on, you can quickly activate accessibility features in two steps:\n\nStep 1: Press and hold the power button until you hear a sound or feel a vibration.\n\nStep 2: Touch and hold two fingers until you hear audio confirmation.\n\nIf the device has multiple users, using this shortcut on the lock screen temporarily enables accessibility until the device is unlocked.</string>
<!-- Title for the accessibility preference to high contrast text. [CHAR LIMIT=35] -->
<string name="accessibility_toggle_high_text_contrast_preference_title">High contrast text</string>
<!-- Title for the accessibility preference to auto update screen magnification. [CHAR LIMIT=35] -->
@@ -5710,7 +5721,6 @@
<string name="keywords_display">screen, touchscreen</string>
<string name="keywords_display_brightness_level">dim screen, touchscreen, battery</string>
<string name="keywords_display_auto_brightness">dim screen, touchscreen, battery</string>
- <string name="keywords_display_night_mode">dark theme, night mode, dim screen, invert brightness</string>
<string name="keywords_display_wallpaper">background, personalize, customize display</string>
<string name="keywords_display_font_size">text size</string>
<string name="keywords_display_cast_screen">project, cast</string>
@@ -5742,6 +5752,7 @@
<string name="keywords_color_temperature">color temperature D65 D73 white yellow blue warm cool</string>
<string name="keywords_lockscreen">slide to unlock, password, pattern, PIN</string>
<string name="keywords_profile_challenge">work challenge, work, profile</string>
+ <string name="keywords_unification">work profile, managed profile, unify, unification, work, profile</string>
<!-- NFC Wi-Fi pairing/setup strings-->
@@ -6478,7 +6489,7 @@
<string name="domain_urls_summary_one">Open <xliff:g id="domain" example="mail.google.com">%s</xliff:g></string>
<!-- Summary of number of App that can open several domain URLs [CHAR LIMIT=45] -->
- <string name="domain_urls_summary_some">Open <xliff:g id="domain" example="mail.google.com">%s</xliff:g> and related URLs</string>
+ <string name="domain_urls_summary_some">Open <xliff:g id="domain" example="mail.google.com">%s</xliff:g> and other URLs</string>
<!-- Description of settings item that leads to list of all apps with Domain URLs [CHAR LIMIT=NONE] -->
<plurals name="domain_urls_apps_summary">
@@ -6893,7 +6904,7 @@
<!-- Description for the screen zoom level that makes interface elements small. [CHAR LIMIT=24] -->
<string name="screen_zoom_summary_small">Small</string>
<!-- Description for the device's default screen zoom level. [CHAR LIMIT=24] -->
- <string name="screen_zoom_summary_normal">Normal</string>
+ <string name="screen_zoom_summary_default">Default</string>
<!-- Description for the screen zoom level that makes interface elements large. [CHAR LIMIT=24] -->
<string name="screen_zoom_summary_large">Large</string>
<!-- Description for the screen zoom level that makes interface elements larger. [CHAR LIMIT=24] -->
@@ -7183,4 +7194,56 @@
<item>@*android:string/gigabyteShort</item>
</string-array>
+ <!-- Notification log debug tool: missing title -->
+ <string name="notification_log_no_title">(none)</string>
+ <!-- Notification log debug tool: delimiter between header and field data -->
+ <string name="notification_log_details_delimiter">": "</string>
+ <!-- Notification log debug tool: header: package name -->
+ <string name="notification_log_details_package">pkg</string>
+ <!-- Notification log debug tool: header: notification key -->
+ <string name="notification_log_details_key">key</string>
+ <!-- Notification log debug tool: header: notification group -->
+ <string name="notification_log_details_group">group</string>
+ <!-- Notification log debug tool: header: notification group summary suffix -->
+ <string name="notification_log_details_group_summary"> (summary)</string>
+ <!-- Notification log debug tool: header: notification visibility -->
+ <string name="notification_log_details_visibility">visibility</string>
+ <!-- Notification log debug tool: header: notification public version -->
+ <string name="notification_log_details_public_version">publicVersion</string>
+ <!-- Notification log debug tool: header: notification priority -->
+ <string name="notification_log_details_priority">priority</string>
+ <!-- Notification log debug tool: header: notification importance -->
+ <string name="notification_log_details_importance">importance</string>
+ <!-- Notification log debug tool: header: notification importance explanation -->
+ <string name="notification_log_details_explanation">explanation</string>
+ <!-- Notification log debug tool: header: notification contentIntent field -->
+ <string name="notification_log_details_content_intent">intent</string>
+ <!-- Notification log debug tool: header: notification deleteIntent field -->
+ <string name="notification_log_details_delete_intent">delete intent</string>
+ <!-- Notification log debug tool: header: notification fullScreenIntent field -->
+ <string name="notification_log_details_full_screen_intent">full screen intent</string>
+ <!-- Notification log debug tool: header: notification actions list -->
+ <string name="notification_log_details_actions">actions</string>
+ <!-- Notification log debug tool: header: title -->
+ <string name="notification_log_details_title">title</string>
+ <!-- Notification log debug tool: header: notification action remoteinput -->
+ <string name="notification_log_details_remoteinput">remote inputs</string>
+ <!-- Notification log debug tool: header: notification contentView -->
+ <string name="notification_log_details_content_view">custom view</string>
+ <!-- Notification log debug tool: header: notification extras -->
+ <string name="notification_log_details_extras">extras</string>
+ <!-- Notification log debug tool: header: notification icon -->
+ <string name="notification_log_details_icon">icon</string>
+ <!-- Notification log debug tool: header: notification size -->
+ <string name="notification_log_details_parcel">parcel size</string>
+ <!-- Notification log debug tool: notification ashmem size -->
+ <string name="notification_log_details_ashmem">ashmem</string>
+ <!-- Notification log debug tool: header: notification sound info -->
+ <string name="notification_log_details_sound">sound</string>
+ <!-- Notification log debug tool: header: notification vibration info -->
+ <string name="notification_log_details_vibrate">vibrate</string>
+ <!-- Notification log debug tool: the word 'default' -->
+ <string name="notification_log_details_default">default</string>
+ <!-- Notification log debug tool: the word 'none' -->
+ <string name="notification_log_details_none">none</string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 70b5005..acd658f 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -373,8 +373,8 @@
<style name="PreviewPagerPageIndicator">
<item name="dotGap">8dp</item>
- <item name="pageIndicatorColor">@android:color/tertiary_text_light</item>
- <item name="currentPageIndicatorColor">@android:color/primary_text_light</item>
+ <item name="pageIndicatorColor">?android:attr/colorControlNormal</item>
+ <item name="currentPageIndicatorColor">?android:attr/colorControlActivated</item>
</style>
<style name="LanguageCheckboxAndLabel">
diff --git a/res/xml/development_prefs.xml b/res/xml/development_prefs.xml
index 53ac1bb..1b056b8 100644
--- a/res/xml/development_prefs.xml
+++ b/res/xml/development_prefs.xml
@@ -60,13 +60,6 @@
android:summary="@string/runningservices_settings_summary"
android:fragment="com.android.settings.applications.RunningServices" />
- <DropDownPreference
- android:key="night_mode"
- android:title="@string/night_mode_title"
- android:summary="%s"
- android:entries="@array/night_mode_entries"
- android:entryValues="@array/night_mode_values" />
-
<PreferenceScreen
android:key="convert_to_file_encryption"
android:title="@string/convert_to_file_encryption"
@@ -348,9 +341,11 @@
android:entries="@array/app_process_limit_entries"
android:entryValues="@array/app_process_limit_values" />
+ <!-- hiding for now.
<Preference
android:key="background_check"
android:title="@string/background_check_pref" />
+ -->
<SwitchPreference
android:key="show_all_anrs"
@@ -370,11 +365,6 @@
android:key="force_resizable_activities"
android:title="@string/force_resizable_activities"
android:summary="@string/force_resizable_activities_summary"/>
-
- <SwitchPreference
- android:key="enable_freeform_support"
- android:title="@string/enable_freeform_support"
- android:summary="@string/enable_freeform_support_summary"/>
</PreferenceCategory>
</PreferenceScreen>
diff --git a/res/xml/fingerprint_enroll_introduction_items.xml b/res/xml/fingerprint_enroll_introduction_items.xml
index 3368843..4cb18a6 100644
--- a/res/xml/fingerprint_enroll_introduction_items.xml
+++ b/res/xml/fingerprint_enroll_introduction_items.xml
@@ -19,13 +19,8 @@
<Item
android:enabled="false"
- android:layout="@layout/suw_items_description"
- android:title="@string/security_settings_fingerprint_enroll_introduction_message" />
-
- <Item
- android:enabled="false"
- android:id="@+id/fingerprint_introduction_message_warning"
- android:layout="@layout/suw_items_description" />
+ android:id="@+id/fingerprint_introduction_message"
+ android:layout="@layout/suw_item_link_description"/>
<Item
android:id="@+id/next_button"
diff --git a/res/xml/security_settings_encryption_interstitial.xml b/res/xml/security_settings_encryption_interstitial.xml
new file mode 100644
index 0000000..6ee6bdd
--- /dev/null
+++ b/res/xml/security_settings_encryption_interstitial.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/lock_settings_picker_title"
+ android:key="lock_settings_picker">
+
+ <Preference
+ android:key="encrypt_require_password"
+ android:persistent="false"/>
+
+ <Preference
+ android:key="encrypt_dont_require_password"
+ android:persistent="false"/>
+
+</PreferenceScreen>
diff --git a/res/xml/security_settings_lockscreen_profile.xml b/res/xml/security_settings_lockscreen_profile.xml
new file mode 100644
index 0000000..8f99c62
--- /dev/null
+++ b/res/xml/security_settings_lockscreen_profile.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+ android:title="@string/security_settings_title">
+
+ <PreferenceScreen
+ android:key="unlock_set_or_change_profile"
+ android:title="@string/unlock_set_unlock_launch_picker_title_profile"
+ android:summary="@string/unlock_set_unlock_mode_off"
+ settings:keywords="@string/keywords_lockscreen"
+ android:persistent="false"/>
+
+</PreferenceScreen>
diff --git a/res/xml/security_settings_password_profile.xml b/res/xml/security_settings_password_profile.xml
new file mode 100644
index 0000000..7aff0fd
--- /dev/null
+++ b/res/xml/security_settings_password_profile.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+ android:title="@string/security_settings_title">
+
+ <PreferenceScreen
+ android:key="unlock_set_or_change_profile"
+ android:title="@string/unlock_set_unlock_launch_picker_title_profile"
+ android:summary="@string/unlock_set_unlock_mode_password"
+ settings:keywords="@string/keywords_lockscreen"
+ android:persistent="false"/>
+
+</PreferenceScreen>
diff --git a/res/xml/security_settings_pattern_profile.xml b/res/xml/security_settings_pattern_profile.xml
new file mode 100644
index 0000000..2010e0d
--- /dev/null
+++ b/res/xml/security_settings_pattern_profile.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+ android:title="@string/security_settings_title">
+
+ <PreferenceScreen
+ android:key="unlock_set_or_change_profile"
+ android:title="@string/unlock_set_unlock_launch_picker_title_profile"
+ android:summary="@string/unlock_set_unlock_mode_pattern"
+ settings:keywords="@string/keywords_lockscreen"
+ android:persistent="false"/>
+
+ <SwitchPreference
+ android:key="visiblepattern_profile"
+ android:title="@string/lockpattern_settings_enable_visible_pattern_title_profile"/>
+
+</PreferenceScreen>
diff --git a/res/xml/security_settings_pin_profile.xml b/res/xml/security_settings_pin_profile.xml
new file mode 100644
index 0000000..5c83072
--- /dev/null
+++ b/res/xml/security_settings_pin_profile.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+ android:title="@string/security_settings_title">
+
+ <PreferenceScreen
+ android:key="unlock_set_or_change_profile"
+ android:title="@string/unlock_set_unlock_launch_picker_title_profile"
+ android:summary="@string/unlock_set_unlock_mode_pin"
+ settings:keywords="@string/keywords_lockscreen"
+ android:persistent="false"/>
+
+</PreferenceScreen>
diff --git a/res/xml/security_settings_profile.xml b/res/xml/security_settings_profile.xml
index 1c10b79..55dd8ef 100644
--- a/res/xml/security_settings_profile.xml
+++ b/res/xml/security_settings_profile.xml
@@ -22,12 +22,6 @@
android:key="security_category_profile"
android:title="@string/lock_settings_profile_title">
- <PreferenceScreen
- android:key="profile_challenge"
- android:title="@string/lock_settings_profile_label"
- settings:keywords="@string/keywords_profile_challenge"
- android:persistent="false"/>
-
</PreferenceCategory>
</PreferenceScreen>
diff --git a/res/xml/security_settings_unification.xml b/res/xml/security_settings_unification.xml
new file mode 100644
index 0000000..79b8b7d
--- /dev/null
+++ b/res/xml/security_settings_unification.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
+ android:title="@string/security_settings_title">
+
+ <SwitchPreference
+ android:key="unification"
+ android:title="@string/lock_settings_profile_unification_title"
+ android:summary="@string/lock_settings_profile_unification_summary"
+ settings:keywords="@string/keywords_unification"/>
+
+</PreferenceScreen>
diff --git a/src/com/android/settings/BugreportPreference.java b/src/com/android/settings/BugreportPreference.java
index 3b7d169..68ee562 100644
--- a/src/com/android/settings/BugreportPreference.java
+++ b/src/com/android/settings/BugreportPreference.java
@@ -32,6 +32,9 @@
import android.widget.TextView;
import android.widget.Toast;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
+
public class BugreportPreference extends CustomDialogPreference {
private static final String TAG = "BugreportPreference";
@@ -107,6 +110,18 @@
private void takeBugreport(int bugreportType) {
try {
+ switch (bugreportType) {
+ case ActivityManager.BUGREPORT_OPTION_FULL:
+ MetricsLogger.action(getDialog().getContext(),
+ MetricsEvent.ACTION_BUGREPORT_FROM_SETTINGS_FULL);
+ break;
+ case ActivityManager.BUGREPORT_OPTION_INTERACTIVE:
+ MetricsLogger.action(getDialog().getContext(),
+ MetricsEvent.ACTION_BUGREPORT_FROM_SETTINGS_INTERACTIVE);
+ break;
+ default:
+ Log.w(TAG, "Unknown bugreportType: " + bugreportType);
+ }
ActivityManagerNative.getDefault().requestBugReport(bugreportType);
} catch (RemoteException e) {
Log.e(TAG, "error taking bugreport (bugreportType=" + bugreportType + ")", e);
diff --git a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
index ad1d2eb..090d4be 100644
--- a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
+++ b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
@@ -83,6 +83,7 @@
// Only take this argument into account if it belongs to the current profile.
Intent intent = getActivity().getIntent();
mEffectiveUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras());
+ mAllowFpAuthentication = mAllowFpAuthentication && !isFingerprintDisabledByAdmin();
mLockPatternUtils = new LockPatternUtils(getActivity());
}
@@ -113,6 +114,13 @@
}
}
+ private boolean isFingerprintDisabledByAdmin() {
+ DevicePolicyManager dpm = (DevicePolicyManager) getActivity().getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ final int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, mEffectiveUserId);
+ return (disabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) != 0;
+ }
+
@Override
public void onResume() {
super.onResume();
diff --git a/src/com/android/settings/CopyablePreference.java b/src/com/android/settings/CopyablePreference.java
index b1f101d..03147c2 100644
--- a/src/com/android/settings/CopyablePreference.java
+++ b/src/com/android/settings/CopyablePreference.java
@@ -30,6 +30,10 @@
super(context, attrs);
}
+ public CopyablePreference(Context context) {
+ this(context, null);
+ }
+
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
@@ -45,10 +49,14 @@
});
}
- public static void copyPreference(Context context, Preference pref) {
+ public CharSequence getCopyableText() {
+ return getSummary();
+ }
+
+ public static void copyPreference(Context context, CopyablePreference pref) {
ClipboardManager cm =
(ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
- cm.setText(pref.getSummary());
+ cm.setText(pref.getCopyableText());
Toast.makeText(context, com.android.internal.R.string.text_copied, Toast.LENGTH_SHORT)
.show();
}
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index 943a4e6..79ea0cb 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -178,7 +178,6 @@
private static final String MOBILE_DATA_ALWAYS_ON = "mobile_data_always_on";
private static final String KEY_COLOR_MODE = "color_mode";
private static final String FORCE_RESIZABLE_KEY = "force_resizable_activities";
- private static final String ENABLE_FREEFORM_SUPPORT_KEY = "enable_freeform_support";
private static final String COLOR_TEMPERATURE_KEY = "color_temperature";
private static final String BLUETOOTH_DISABLE_ABSOLUTE_VOLUME_KEY =
@@ -202,7 +201,6 @@
private static final String TERMINAL_APP_PACKAGE = "com.android.terminal";
- private static final String KEY_NIGHT_MODE = "night_mode";
private static final String KEY_CONVERT_FBE = "convert_to_file_encryption";
private static final String OTA_DISABLE_AUTOMATIC_UPDATE_KEY = "ota_disable_automatic_update";
@@ -292,14 +290,10 @@
private SwitchPreference mShowAllANRs;
- private DropDownPreference mNightModePreference;
-
private ColorModePreference mColorModePreference;
private SwitchPreference mForceResizable;
- private SwitchPreference mEnableFreeformSupport;
-
private SwitchPreference mColorTemperaturePreference;
private final ArrayList<Preference> mAllPrefs = new ArrayList<Preference>();
@@ -440,7 +434,6 @@
mSimulateColorSpace = addListPreference(SIMULATE_COLOR_SPACE);
mUSBAudio = findAndInitSwitchPref(USB_AUDIO_KEY);
mForceResizable = findAndInitSwitchPref(FORCE_RESIZABLE_KEY);
- mEnableFreeformSupport = findAndInitSwitchPref(ENABLE_FREEFORM_SUPPORT_KEY);
mImmediatelyDestroyActivities = (SwitchPreference) findPreference(
IMMEDIATELY_DESTROY_ACTIVITIES_KEY);
@@ -479,27 +472,6 @@
mOtaDisableAutomaticUpdate = findAndInitSwitchPref(OTA_DISABLE_AUTOMATIC_UPDATE_KEY);
- mNightModePreference = (DropDownPreference) findPreference(KEY_NIGHT_MODE);
- final UiModeManager uiManager = (UiModeManager) getSystemService(
- Context.UI_MODE_SERVICE);
- final int currentNightMode = uiManager.getNightMode();
- mNightModePreference.setValue(String.valueOf(currentNightMode));
- mNightModePreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- try {
- final int value = Integer.parseInt((String) newValue);
- final UiModeManager uiManager = (UiModeManager) getSystemService(
- Context.UI_MODE_SERVICE);
- uiManager.setNightMode(value);
- return true;
- } catch (NumberFormatException e) {
- Log.e(TAG, "could not persist night mode setting", e);
- return false;
- }
- }
- });
-
mColorModePreference = (ColorModePreference) findPreference(KEY_COLOR_MODE);
mColorModePreference.updateCurrentAndSupported();
if (mColorModePreference.getTransformsCount() < 2) {
@@ -723,7 +695,6 @@
updateSimulateColorSpace();
updateUSBAudioOptions();
updateForceResizableOptions();
- updateEnableFreeformWindowsSupportOptions();
updateWebViewMultiprocessOptions();
updateWebViewProviderOptions();
updateOemUnlockOptions();
@@ -1377,17 +1348,6 @@
mForceResizable.isChecked() ? 1 : 0);
}
- private void updateEnableFreeformWindowsSupportOptions() {
- updateSwitchPreference(mEnableFreeformSupport, Settings.Global.getInt(getContentResolver(),
- Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0);
- }
-
- private void writeEnableFreeformWindowsSupportOptions() {
- Settings.Global.putInt(getContentResolver(),
- Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT,
- mEnableFreeformSupport.isChecked() ? 1 : 0);
- }
-
private void updateForceRtlOptions() {
updateSwitchPreference(mForceRtlLayout,
Settings.Global.getInt(getActivity().getContentResolver(),
@@ -1932,8 +1892,6 @@
writeUSBAudioOptions();
} else if (preference == mForceResizable) {
writeForceResizableOptions();
- } else if (preference == mEnableFreeformSupport){
- writeEnableFreeformWindowsSupportOptions();
} else if (INACTIVE_APPS_KEY.equals(preference.getKey())) {
startInactiveAppsFragment();
} else if (BACKGROUND_CHECK_KEY.equals(preference.getKey())) {
diff --git a/src/com/android/settings/EncryptionInterstitial.java b/src/com/android/settings/EncryptionInterstitial.java
index b237813..16c5a55 100644
--- a/src/com/android/settings/EncryptionInterstitial.java
+++ b/src/com/android/settings/EncryptionInterstitial.java
@@ -22,17 +22,14 @@
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
+import android.support.v7.preference.Preference;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
-import android.widget.Button;
-import android.widget.RadioButton;
import android.widget.TextView;
import com.android.internal.logging.MetricsProto.MetricsEvent;
@@ -63,10 +60,6 @@
public static Intent createStartIntent(Context ctx, int quality,
boolean requirePasswordDefault, Intent unlockMethodIntent) {
return new Intent(ctx, EncryptionInterstitial.class)
- .putExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, true)
- .putExtra(EXTRA_PREFS_SET_BACK_TEXT, (String) null)
- .putExtra(EXTRA_PREFS_SET_NEXT_TEXT, ctx.getString(
- R.string.encryption_continue_button))
.putExtra(EXTRA_PASSWORD_QUALITY, quality)
.putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, R.string.encryption_interstitial_header)
.putExtra(EXTRA_REQUIRE_PASSWORD, requirePasswordDefault)
@@ -74,12 +67,15 @@
}
public static class EncryptionInterstitialFragment extends SettingsPreferenceFragment
- implements View.OnClickListener, OnClickListener {
+ implements DialogInterface.OnClickListener {
private static final int ACCESSIBILITY_WARNING_DIALOG = 1;
- private RadioButton mRequirePasswordToDecryptButton;
- private RadioButton mDontRequirePasswordToDecryptButton;
- private TextView mEncryptionMessage;
+ private static final String KEY_ENCRYPT_REQUIRE_PASSWORD = "encrypt_require_password";
+ private static final String KEY_ENCRYPT_DONT_REQUIRE_PASSWORD =
+ "encrypt_dont_require_password";
+
+ private Preference mRequirePasswordToDecrypt;
+ private Preference mDontRequirePasswordToDecrypt;
private boolean mPasswordRequired;
private Intent mUnlockMethodIntent;
@@ -89,20 +85,13 @@
}
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- return inflater.inflate(R.layout.encryption_interstitial, container, false);
- }
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- mRequirePasswordToDecryptButton =
- (RadioButton) view.findViewById(R.id.encrypt_require_password);
- mDontRequirePasswordToDecryptButton =
- (RadioButton) view.findViewById(R.id.encrypt_dont_require_password);
- mEncryptionMessage =
- (TextView) view.findViewById(R.id.encryption_message);
+ addPreferencesFromResource(R.xml.security_settings_encryption_interstitial);
+
+ mRequirePasswordToDecrypt = findPreference(KEY_ENCRYPT_REQUIRE_PASSWORD);
+ mDontRequirePasswordToDecrypt = findPreference(KEY_ENCRYPT_DONT_REQUIRE_PASSWORD);
boolean forFingerprint = getActivity().getIntent().getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
Intent intent = getActivity().getIntent();
@@ -135,26 +124,22 @@
disableId = R.string.encrypt_dont_require_password;
break;
}
- mEncryptionMessage.setText(msgId);
+ TextView message = createHeaderView();
+ message.setText(msgId);
+ setHeaderView(message);
- mRequirePasswordToDecryptButton.setOnClickListener(this);
- mRequirePasswordToDecryptButton.setText(enableId);
+ mRequirePasswordToDecrypt.setTitle(enableId);
- mDontRequirePasswordToDecryptButton.setOnClickListener(this);
- mDontRequirePasswordToDecryptButton.setText(disableId);
+ mDontRequirePasswordToDecrypt.setTitle(disableId);
setRequirePasswordState(getActivity().getIntent().getBooleanExtra(
EXTRA_REQUIRE_PASSWORD, true));
+ }
- Button nextButton = getNextButton();
- if (nextButton != null) {
- nextButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- startLockIntent();
- }
- });
- }
+ protected TextView createHeaderView() {
+ TextView message = (TextView) LayoutInflater.from(getActivity()).inflate(
+ R.layout.encryption_interstitial_header, null, false);
+ return message;
}
protected void startLockIntent() {
@@ -177,18 +162,22 @@
}
@Override
- public void onClick(View v) {
- if (v == mRequirePasswordToDecryptButton) {
+ public boolean onPreferenceTreeClick(Preference preference) {
+ final String key = preference.getKey();
+ if (key.equals(KEY_ENCRYPT_REQUIRE_PASSWORD)) {
final boolean accEn = AccessibilityManager.getInstance(getActivity()).isEnabled();
if (accEn && !mPasswordRequired) {
setRequirePasswordState(false); // clear the UI state
showDialog(ACCESSIBILITY_WARNING_DIALOG);
} else {
setRequirePasswordState(true);
+ startLockIntent();
}
} else {
setRequirePasswordState(false);
+ startLockIntent();
}
+ return true;
}
@Override
@@ -242,14 +231,13 @@
private void setRequirePasswordState(boolean required) {
mPasswordRequired = required;
- mRequirePasswordToDecryptButton.setChecked(required);
- mDontRequirePasswordToDecryptButton.setChecked(!required);
}
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
setRequirePasswordState(true);
+ startLockIntent();
} else if (which == DialogInterface.BUTTON_NEGATIVE) {
setRequirePasswordState(false);
}
diff --git a/src/com/android/settings/ProfileChallengePreferenceFragment.java b/src/com/android/settings/ProfileChallengePreferenceFragment.java
deleted file mode 100644
index 4c65441..0000000
--- a/src/com/android/settings/ProfileChallengePreferenceFragment.java
+++ /dev/null
@@ -1,351 +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;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.DialogFragment;
-import android.app.FragmentManager;
-import android.app.admin.DevicePolicyManager;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.pm.UserInfo;
-import android.hardware.fingerprint.Fingerprint;
-import android.hardware.fingerprint.FingerprintManager;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.support.v14.preference.SwitchPreference;
-import android.support.v7.preference.ListPreference;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.Preference.OnPreferenceChangeListener;
-import android.support.v7.preference.Preference.OnPreferenceClickListener;
-import android.util.Log;
-import android.support.v7.preference.PreferenceCategory;
-import android.support.v7.preference.PreferenceGroup;
-import android.support.v7.preference.PreferenceScreen;
-
-import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.settings.fingerprint.FingerprintEnrollIntroduction;
-import com.android.settings.fingerprint.FingerprintSettings;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Settings for the Profile Challenge.
- */
-public class ProfileChallengePreferenceFragment extends SettingsPreferenceFragment
- implements OnPreferenceChangeListener {
- private static final String TAG = "WorkChallengePreferenceFragment";
-
- private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
- private static final String KEY_VISIBLE_PATTERN = "visiblepattern";
- private static final String KEY_SECURITY_CATEGORY = "security_category";
- private static final String KEY_UNIFICATION = "unification";
- public static final String TAG_UNIFICATION_DIALOG = "unification_dialog";
-
- private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
- private static final int UNIFY_LOCK_CONFIRM_DEVICE_REQUEST = 124;
- private static final int UNIFY_LOCK_CONFIRM_PROFILE_REQUEST = 125;
-
- // Not all preferences make sense for the Work Challenge, this is a whitelist.
- private static final Set<String> ALLOWED_PREFERENCE_KEYS = new HashSet<>();
- {
- ALLOWED_PREFERENCE_KEYS.add(KEY_UNLOCK_SET_OR_CHANGE);
- ALLOWED_PREFERENCE_KEYS.add(KEY_VISIBLE_PATTERN);
- }
- // These switch preferences need special handling since they're not all stored in Settings.
- private static final Set<String> SWITCH_PREFERENCE_KEYS = new HashSet<>();
- {
- SWITCH_PREFERENCE_KEYS.add(KEY_VISIBLE_PATTERN);
- }
-
- private LockPatternUtils mLockPatternUtils;
- private int mProfileUserId;
-
- private String mCurrentDevicePassword;
- private String mCurrentProfilePassword;
-
- private SwitchPreference mVisiblePattern;
-
- @Override
- protected int getMetricsCategory() {
- return MetricsEvent.PROFILE_CHALLENGE;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mLockPatternUtils = new LockPatternUtils(getActivity());
-
- mProfileUserId = getArguments().getInt(Intent.EXTRA_USER_ID, -1);
- if (mProfileUserId == -1) {
- finish();
- }
- }
-
- @Override
- public boolean onPreferenceTreeClick(Preference preference) {
- final String key = preference.getKey();
- if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) {
- Bundle extras = new Bundle();
- extras.putInt(Intent.EXTRA_USER_ID, mProfileUserId);
- startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
- R.string.lock_settings_picker_title, SET_OR_CHANGE_LOCK_METHOD_REQUEST, extras);
- return true;
- } else if (KEY_UNIFICATION.equals(key)) {
- UnificationConfirmationDialog dialog =
- UnificationConfirmationDialog.newIntance(mProfileUserId);
- dialog.show(getChildFragmentManager(), TAG_UNIFICATION_DIALOG);
- return true;
- }
- return super.onPreferenceTreeClick(preference);
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object value) {
- final String key = preference.getKey();
- if (KEY_VISIBLE_PATTERN.equals(key)) {
- mLockPatternUtils.setVisiblePatternEnabled((Boolean) value, mProfileUserId);
- return true;
- }
- return false;
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == UNIFY_LOCK_CONFIRM_DEVICE_REQUEST && resultCode == Activity.RESULT_OK) {
- mCurrentDevicePassword =
- data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
- launchConfirmProfileLockForUnification();
- return;
- } else if (requestCode == UNIFY_LOCK_CONFIRM_PROFILE_REQUEST
- && resultCode == Activity.RESULT_OK) {
- mCurrentProfilePassword =
- data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
- unifyLocks();
- return;
- }
- }
-
- private void launchConfirmDeviceLockForUnification() {
- final String title = getActivity().getString(
- R.string.lock_settings_profile_screen_lock_title);
- final ChooseLockSettingsHelper helper =
- new ChooseLockSettingsHelper(getActivity(), this);
- if (!helper.launchConfirmationActivity(
- UNIFY_LOCK_CONFIRM_DEVICE_REQUEST, title, true, UserHandle.myUserId())) {
- launchConfirmProfileLockForUnification();
- }
- }
-
- private void launchConfirmProfileLockForUnification() {
- final String title = getActivity().getString(
- R.string.lock_settings_profile_screen_lock_title);
- final ChooseLockSettingsHelper helper =
- new ChooseLockSettingsHelper(getActivity(), this);
- if (!helper.launchConfirmationActivity(
- UNIFY_LOCK_CONFIRM_PROFILE_REQUEST, title, true, mProfileUserId)) {
- unifyLocks();
- createPreferenceHierarchy();
- }
- }
-
- private void unifyLocks() {
- int profileQuality = mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileUserId);
- mLockPatternUtils.clearLock(mProfileUserId);
- mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileUserId, false);
- if (profileQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
- mLockPatternUtils.saveLockPattern(
- LockPatternUtils.stringToPattern(mCurrentProfilePassword),
- mCurrentDevicePassword, UserHandle.myUserId());
- } else {
- mLockPatternUtils.saveLockPassword(
- mCurrentProfilePassword, mCurrentDevicePassword,
- profileQuality, UserHandle.myUserId());
- }
- mCurrentDevicePassword = null;
- mCurrentProfilePassword = null;
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- // Make sure we reload the preference hierarchy since some of these settings
- // depend on others...
- createPreferenceHierarchy();
-
- if (mVisiblePattern != null) {
- mVisiblePattern.setChecked(mLockPatternUtils.isVisiblePatternEnabled(
- mProfileUserId));
- }
- }
-
- private void createPreferenceHierarchy() {
- PreferenceScreen root = getPreferenceScreen();
- if (root != null) {
- root.removeAll();
- }
- addPreferencesFromResource(R.xml.profile_challenge_settings);
- root = getPreferenceScreen();
-
- // Add options for lock/unlock screen
- final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils);
- addPreferencesFromResource(resid);
-
- mVisiblePattern = (SwitchPreference) root.findPreference(KEY_VISIBLE_PATTERN);
-
- removeNonWhitelistedItems(root);
-
- PreferenceGroup securityCategory = (PreferenceGroup)
- root.findPreference(KEY_SECURITY_CATEGORY);
- if (securityCategory != null) {
- maybeAddFingerprintPreference(securityCategory);
- if (mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileUserId)) {
- maybeAddUnificationPreference(securityCategory);
- } else {
- Preference lockPreference =
- securityCategory.findPreference(KEY_UNLOCK_SET_OR_CHANGE);
- String summary =
- getContext().getString(R.string.lock_settings_profile_unified_summary);
- lockPreference.setSummary(summary);
- }
- }
- }
-
- private void maybeAddUnificationPreference(PreferenceGroup securityCategory) {
- if (mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileUserId)
- >= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
- && mLockPatternUtils.isSeparateProfileChallengeAllowedToUnify(mProfileUserId)) {
- Preference unificationPreference = new Preference(securityCategory.getContext());
- unificationPreference.setKey(KEY_UNIFICATION);
- unificationPreference.setTitle(R.string.lock_settings_profile_unification_title);
- unificationPreference.setSummary(R.string.lock_settings_profile_unification_summary);
- securityCategory.addPreference(unificationPreference);
- }
- }
-
- private void maybeAddFingerprintPreference(PreferenceGroup securityCategory) {
- Preference fingerprintPreference =
- FingerprintSettings.getFingerprintPreferenceForUser(getActivity(), mProfileUserId);
- if (fingerprintPreference != null) {
- securityCategory.addPreference(fingerprintPreference);
- }
- }
-
- private void removeNonWhitelistedItems(PreferenceGroup prefScreen) {
- int numPreferences = prefScreen.getPreferenceCount();
- int i = 0;
- while (i < numPreferences) {
- final Preference pref = prefScreen.getPreference(i);
- // Recursively look into categories and remove them if they are empty.
- if (pref instanceof PreferenceCategory) {
- PreferenceCategory category = (PreferenceCategory) pref;
- removeNonWhitelistedItems(category);
- if (category.getPreferenceCount() == 0) {
- prefScreen.removePreference(category);
- --i;
- --numPreferences;
- }
- } else if (ALLOWED_PREFERENCE_KEYS.contains(pref.getKey())) {
- if (SWITCH_PREFERENCE_KEYS.contains(pref.getKey())) {
- pref.setOnPreferenceChangeListener(this);
- }
- } else {
- prefScreen.removePreference(pref);
- --i;
- --numPreferences;
- }
- ++i;
- }
- }
-
- private int getResIdForLockUnlockScreen(Context context,
- LockPatternUtils lockPatternUtils) {
- int resid = 0;
- if (!lockPatternUtils.isSecure(mProfileUserId)) {
- resid = R.xml.security_settings_lockscreen;
- } else {
- switch (lockPatternUtils.getKeyguardStoredPasswordQuality(mProfileUserId)) {
- case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
- resid = R.xml.security_settings_pattern;
- break;
- case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
- case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
- resid = R.xml.security_settings_pin;
- break;
- case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
- case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
- case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
- resid = R.xml.security_settings_password;
- break;
- }
- }
- return resid;
- }
-
- public static class UnificationConfirmationDialog extends DialogFragment {
-
- public static UnificationConfirmationDialog newIntance(int userId) {
- UnificationConfirmationDialog dialog = new UnificationConfirmationDialog();
- return dialog;
- }
-
- @Override
- public void show(FragmentManager manager, String tag) {
- if (manager.findFragmentByTag(tag) == null) {
- // Prevent opening multiple dialogs if tapped on button quickly
- super.show(manager, tag);
- }
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final ProfileChallengePreferenceFragment parentFragment =
- ((ProfileChallengePreferenceFragment) getParentFragment());
- return new AlertDialog.Builder(getActivity())
- .setTitle(R.string.lock_settings_profile_unification_dialog_title)
- .setMessage(R.string.lock_settings_profile_unification_dialog_body)
- .setPositiveButton(R.string.okay,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int whichButton) {
- parentFragment.launchConfirmDeviceLockForUnification();
- }
- }
- )
- .setNegativeButton(R.string.cancel,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int whichButton) {
- dismiss();
- }
- }
- )
- .create();
- }
- }
-}
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index b4cbab2..8464462 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -19,6 +19,9 @@
import android.app.Activity;
import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.FragmentManager;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
@@ -85,14 +88,20 @@
// Lock Settings
private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
- private static final String KEY_UNLOCK_SET_OR_CHANGE_PROFILE = "profile_challenge";
+ private static final String KEY_UNLOCK_SET_OR_CHANGE_PROFILE = "unlock_set_or_change_profile";
+ private static final String KEY_VISIBLE_PATTERN_PROFILE = "visiblepattern_profile";
private static final String KEY_SECURITY_CATEGORY = "security_category";
private static final String KEY_DEVICE_ADMIN_CATEGORY = "device_admin_category";
private static final String KEY_ADVANCED_SECURITY = "advanced_security";
private static final String KEY_MANAGE_TRUST_AGENTS = "manage_trust_agents";
+ private static final String KEY_UNIFICATION = "unification";
private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
private static final int CHANGE_TRUST_AGENT_SETTINGS = 126;
+ private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE = 127;
+ private static final int UNIFY_LOCK_CONFIRM_DEVICE_REQUEST = 128;
+ private static final int UNIFY_LOCK_CONFIRM_PROFILE_REQUEST = 129;
+ private static final String TAG_UNIFICATION_DIALOG = "unification_dialog";
// Misc Settings
private static final String KEY_SIM_LOCK = "sim_lock";
@@ -108,7 +117,7 @@
// These switch preferences need special handling since they're not all stored in Settings.
private static final String SWITCH_PREFERENCE_KEYS[] = {
- KEY_SHOW_PASSWORD, KEY_TOGGLE_INSTALL_APPLICATIONS };
+ KEY_SHOW_PASSWORD, KEY_TOGGLE_INSTALL_APPLICATIONS, KEY_UNIFICATION };
// Only allow one trust agent on the platform.
private static final boolean ONLY_ONE_TRUST_AGENT = true;
@@ -122,6 +131,9 @@
private ChooseLockSettingsHelper mChooseLockSettingsHelper;
private LockPatternUtils mLockPatternUtils;
+ private SwitchPreference mVisiblePatternProfile;
+ private SwitchPreference mUnifyProfile;
+
private SwitchPreference mShowPassword;
private KeyStore mKeyStore;
@@ -136,6 +148,9 @@
private int mProfileChallengeUserId;
+ private String mCurrentDevicePassword;
+ private String mCurrentProfilePassword;
+
@Override
protected int getMetricsCategory() {
return MetricsEvent.SECURITY;
@@ -162,27 +177,33 @@
}
private static int getResIdForLockUnlockScreen(Context context,
- LockPatternUtils lockPatternUtils) {
+ LockPatternUtils lockPatternUtils, int userId) {
+ final boolean isMyUser = userId == MY_USER_ID;
int resid = 0;
- if (!lockPatternUtils.isSecure(MY_USER_ID)) {
- if (lockPatternUtils.isLockScreenDisabled(MY_USER_ID)) {
+ if (!lockPatternUtils.isSecure(userId)) {
+ if (!isMyUser) {
+ resid = R.xml.security_settings_lockscreen_profile;
+ } else if (lockPatternUtils.isLockScreenDisabled(userId)) {
resid = R.xml.security_settings_lockscreen;
} else {
resid = R.xml.security_settings_chooser;
}
} else {
- switch (lockPatternUtils.getKeyguardStoredPasswordQuality(MY_USER_ID)) {
+ switch (lockPatternUtils.getKeyguardStoredPasswordQuality(userId)) {
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
- resid = R.xml.security_settings_pattern;
+ resid = isMyUser ? R.xml.security_settings_pattern
+ : R.xml.security_settings_pattern_profile;
break;
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
- resid = R.xml.security_settings_pin;
+ resid = isMyUser ? R.xml.security_settings_pin
+ : R.xml.security_settings_pin_profile;
break;
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
- resid = R.xml.security_settings_password;
+ resid = isMyUser ? R.xml.security_settings_password
+ : R.xml.security_settings_password_profile;
break;
}
}
@@ -204,20 +225,24 @@
root = getPreferenceScreen();
// Add options for lock/unlock screen
- final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils);
+ final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils, MY_USER_ID);
addPreferencesFromResource(resid);
- List<UserInfo> profiles = mUm.getProfiles(UserHandle.myUserId());
- int numProfiles = profiles.size();
- if (numProfiles > 1) {
- for (int i = 0; i < numProfiles; ++i) {
- UserInfo profile = profiles.get(i);
- if (profile.id != UserHandle.myUserId()) {
- mProfileChallengeUserId = profile.id;
- }
- }
- if (mLockPatternUtils.isSeparateProfileChallengeAllowed(mProfileChallengeUserId)) {
- addPreferencesFromResource(R.xml.security_settings_profile);
+ mProfileChallengeUserId = getManagedProfileId(mUm);
+ if (mProfileChallengeUserId != UserHandle.USER_NULL
+ && mLockPatternUtils.isSeparateProfileChallengeAllowed(mProfileChallengeUserId)) {
+ addPreferencesFromResource(R.xml.security_settings_profile);
+ final int profileResid = getResIdForLockUnlockScreen(
+ getActivity(), mLockPatternUtils, mProfileChallengeUserId);
+ addPreferencesFromResource(profileResid);
+ maybeAddFingerprintPreference(root, mProfileChallengeUserId);
+ addPreferencesFromResource(R.xml.security_settings_unification);
+ if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId)) {
+ Preference lockPreference = root.findPreference(KEY_UNLOCK_SET_OR_CHANGE_PROFILE);
+ String summary = getContext().getString(
+ R.string.lock_settings_profile_unified_summary);
+ lockPreference.setSummary(summary);
+ lockPreference.setEnabled(false);
}
}
@@ -243,10 +268,14 @@
PreferenceGroup securityCategory = (PreferenceGroup)
root.findPreference(KEY_SECURITY_CATEGORY);
if (securityCategory != null) {
- maybeAddFingerprintPreference(securityCategory);
+ maybeAddFingerprintPreference(securityCategory, UserHandle.myUserId());
addTrustAgentSettings(securityCategory);
}
+ mVisiblePatternProfile =
+ (SwitchPreference) root.findPreference(KEY_VISIBLE_PATTERN_PROFILE);
+ mUnifyProfile = (SwitchPreference) root.findPreference(KEY_UNIFICATION);
+
// Append the rest of the settings
addPreferencesFromResource(R.xml.security_settings_misc);
@@ -350,10 +379,10 @@
return root;
}
- private void maybeAddFingerprintPreference(PreferenceGroup securityCategory) {
+ private void maybeAddFingerprintPreference(PreferenceGroup securityCategory, int userId) {
Preference fingerprintPreference =
FingerprintSettings.getFingerprintPreferenceForUser(
- securityCategory.getContext(), UserHandle.myUserId());
+ securityCategory.getContext(), userId);
if (fingerprintPreference != null) {
securityCategory.addPreference(fingerprintPreference);
}
@@ -524,7 +553,13 @@
// depend on others...
createPreferenceHierarchy();
- final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
+ if (mVisiblePatternProfile != null) {
+ mVisiblePatternProfile.setChecked(mLockPatternUtils.isVisiblePatternEnabled(
+ mProfileChallengeUserId));
+ }
+
+ updateUnificationPreference();
+
if (mShowPassword != null) {
mShowPassword.setChecked(Settings.System.getInt(getContentResolver(),
Settings.System.TEXT_SHOW_PASSWORD, 1) != 0);
@@ -535,6 +570,13 @@
}
}
+ private void updateUnificationPreference() {
+ if (mUnifyProfile != null) {
+ mUnifyProfile.setChecked(!mLockPatternUtils.isSeparateProfileChallengeEnabled(
+ mProfileChallengeUserId));
+ }
+ }
+
@Override
public boolean onPreferenceTreeClick(Preference preference) {
final String key = preference.getKey();
@@ -544,8 +586,9 @@
} else if (KEY_UNLOCK_SET_OR_CHANGE_PROFILE.equals(key)) {
Bundle extras = new Bundle();
extras.putInt(Intent.EXTRA_USER_ID, mProfileChallengeUserId);
- startFragment(this, "com.android.settings.ProfileChallengePreferenceFragment",
- R.string.lock_settings_profile_label, SET_OR_CHANGE_LOCK_METHOD_REQUEST, extras);
+ startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
+ R.string.lock_settings_picker_title_profile,
+ SET_OR_CHANGE_LOCK_METHOD_REQUEST_PROFILE, extras);
} else if (KEY_TRUST_AGENT.equals(key)) {
ChooseLockSettingsHelper helper =
new ChooseLockSettingsHelper(this.getActivity(), this);
@@ -576,16 +619,92 @@
mTrustAgentClickIntent = null;
}
return;
+ } else if (requestCode == UNIFY_LOCK_CONFIRM_DEVICE_REQUEST
+ && resultCode == Activity.RESULT_OK) {
+ mCurrentDevicePassword =
+ data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
+ launchConfirmProfileLockForUnification();
+ return;
+ } else if (requestCode == UNIFY_LOCK_CONFIRM_PROFILE_REQUEST
+ && resultCode == Activity.RESULT_OK) {
+ mCurrentProfilePassword =
+ data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
+ unifyLocks();
+ return;
}
createPreferenceHierarchy();
}
+ private void launchConfirmDeviceLockForUnification() {
+ final String title = getActivity().getString(
+ R.string.lock_settings_profile_screen_lock_title);
+ final ChooseLockSettingsHelper helper =
+ new ChooseLockSettingsHelper(getActivity(), this);
+ if (!helper.launchConfirmationActivity(
+ UNIFY_LOCK_CONFIRM_DEVICE_REQUEST, title, true, UserHandle.myUserId())) {
+ launchConfirmProfileLockForUnification();
+ }
+ }
+
+ private void launchConfirmProfileLockForUnification() {
+ final String title = getActivity().getString(
+ R.string.lock_settings_profile_screen_lock_title);
+ final ChooseLockSettingsHelper helper =
+ new ChooseLockSettingsHelper(getActivity(), this);
+ if (!helper.launchConfirmationActivity(
+ UNIFY_LOCK_CONFIRM_PROFILE_REQUEST, title, true, mProfileChallengeUserId)) {
+ unifyLocks();
+ createPreferenceHierarchy();
+ }
+ }
+
+ private void unifyLocks() {
+ int profileQuality =
+ mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileChallengeUserId);
+ mLockPatternUtils.clearLock(mProfileChallengeUserId);
+ mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileChallengeUserId, false);
+ if (profileQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
+ mLockPatternUtils.saveLockPattern(
+ LockPatternUtils.stringToPattern(mCurrentProfilePassword),
+ mCurrentDevicePassword, UserHandle.myUserId());
+ } else {
+ mLockPatternUtils.saveLockPassword(
+ mCurrentProfilePassword, mCurrentDevicePassword,
+ profileQuality, UserHandle.myUserId());
+ }
+ mCurrentDevicePassword = null;
+ mCurrentProfilePassword = null;
+ }
+
+ private void unifyUncompliantLocks() {
+ mLockPatternUtils.clearLock(mProfileChallengeUserId);
+ mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileChallengeUserId, false);
+ startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
+ R.string.lock_settings_picker_title, SET_OR_CHANGE_LOCK_METHOD_REQUEST, null);
+ }
+
@Override
public boolean onPreferenceChange(Preference preference, Object value) {
boolean result = true;
final String key = preference.getKey();
final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
- if (KEY_SHOW_PASSWORD.equals(key)) {
+ if (KEY_VISIBLE_PATTERN_PROFILE.equals(key)) {
+ lockPatternUtils.setVisiblePatternEnabled((Boolean) value, mProfileChallengeUserId);
+ } else if (KEY_UNIFICATION.equals(key)) {
+ if ((Boolean) value) {
+ final boolean compliantForDevice =
+ (mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileChallengeUserId)
+ >= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
+ && mLockPatternUtils.isSeparateProfileChallengeAllowedToUnify(
+ mProfileChallengeUserId));
+ UnificationConfirmationDialog dialog =
+ UnificationConfirmationDialog.newIntance(compliantForDevice);
+ dialog.show(getChildFragmentManager(), TAG_UNIFICATION_DIALOG);
+ } else {
+ mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileChallengeUserId, true);
+ createPreferenceHierarchy();
+ }
+ } else if (KEY_SHOW_PASSWORD.equals(key)) {
Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
((Boolean) value) ? 1 : 0);
lockPatternUtils.setVisiblePasswordEnabled((Boolean) value, MY_USER_ID);
@@ -607,6 +726,21 @@
return R.string.help_url_security;
}
+ private static int getManagedProfileId(UserManager um) {
+ List<UserInfo> profiles = um.getProfiles(MY_USER_ID);
+ int numProfiles = profiles.size();
+ if (numProfiles == 1) {
+ return UserHandle.USER_NULL;
+ }
+ for (int i = 0; i < numProfiles; ++i) {
+ UserInfo profile = profiles.get(i);
+ if (profile.id != MY_USER_ID) {
+ return profile.id;
+ }
+ }
+ return UserHandle.USER_NULL;
+ }
+
/**
* For Search. Please keep it in sync when updating "createPreferenceHierarchy()"
*/
@@ -623,28 +757,20 @@
LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
// Add options for lock/unlock screen
- int resId = getResIdForLockUnlockScreen(context, lockPatternUtils);
+ int resId = getResIdForLockUnlockScreen(context, lockPatternUtils, MY_USER_ID);
SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = resId;
result.add(sir);
final UserManager um = UserManager.get(context);
- List<UserInfo> profiles = um.getProfiles(UserHandle.myUserId());
- int numProfiles = profiles.size();
- if (numProfiles > 1) {
- int profileUserId = -1;
- for (int i = 0; i < numProfiles; ++i) {
- UserInfo profile = profiles.get(i);
- if (profile.id != UserHandle.myUserId()) {
- profileUserId = profile.id;
- }
- }
- if (lockPatternUtils.isSeparateProfileChallengeAllowed(profileUserId)) {
- sir = new SearchIndexableResource(context);
- sir.xmlResId = R.xml.security_settings_profile;
- result.add(sir);
- }
+ final int profileUserId = getManagedProfileId(um);
+ if (profileUserId != UserHandle.USER_NULL
+ && lockPatternUtils.isSeparateProfileChallengeAllowed(profileUserId)) {
+ sir = new SearchIndexableResource(context);
+ sir.xmlResId = getResIdForLockUnlockScreen(
+ context, lockPatternUtils, profileUserId);
+ result.add(sir);
}
if (um.isAdminUser()) {
@@ -720,6 +846,21 @@
result.add(data);
}
+ final LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
+ final int profileUserId = getManagedProfileId(um);
+ if (profileUserId != UserHandle.USER_NULL
+ && lockPatternUtils.isSeparateProfileChallengeAllowed(profileUserId)) {
+ if (lockPatternUtils.getKeyguardStoredPasswordQuality(profileUserId)
+ >= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
+ && lockPatternUtils.isSeparateProfileChallengeAllowedToUnify(
+ profileUserId)) {
+ data = new SearchIndexableRaw(context);
+ data.title = res.getString(R.string.lock_settings_profile_unification_title);
+ data.screenTitle = screenTitle;
+ result.add(data);
+ }
+ }
+
// Credential storage
if (!um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) {
KeyStore keyStore = KeyStore.getInstance();
@@ -735,7 +876,6 @@
}
// Advanced
- final LockPatternUtils lockPatternUtils = new LockPatternUtils(context);
if (lockPatternUtils.isSecure(MY_USER_ID)) {
ArrayList<TrustAgentComponentInfo> agents =
getActiveTrustAgents(context, lockPatternUtils,
@@ -823,13 +963,12 @@
createPreferenceHierarchy();
- final LockPatternUtils lockPatternUtils = mLockPatternUtils;
if (mVisiblePattern != null) {
- mVisiblePattern.setChecked(lockPatternUtils.isVisiblePatternEnabled(
+ mVisiblePattern.setChecked(mLockPatternUtils.isVisiblePatternEnabled(
MY_USER_ID));
}
if (mPowerButtonInstantlyLocks != null) {
- mPowerButtonInstantlyLocks.setChecked(lockPatternUtils.getPowerButtonInstantlyLocks(
+ mPowerButtonInstantlyLocks.setChecked(mLockPatternUtils.getPowerButtonInstantlyLocks(
MY_USER_ID));
}
@@ -1080,4 +1219,58 @@
return true;
}
}
+
+ public static class UnificationConfirmationDialog extends DialogFragment {
+ private static final String EXTRA_COMPLIANT = "compliant";
+
+ public static UnificationConfirmationDialog newIntance(boolean compliant) {
+ UnificationConfirmationDialog dialog = new UnificationConfirmationDialog();
+ Bundle args = new Bundle();
+ args.putBoolean(EXTRA_COMPLIANT, compliant);
+ dialog.setArguments(args);
+ return dialog;
+ }
+
+ @Override
+ public void show(FragmentManager manager, String tag) {
+ if (manager.findFragmentByTag(tag) == null) {
+ // Prevent opening multiple dialogs if tapped on button quickly
+ super.show(manager, tag);
+ }
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final SecuritySettings parentFragment = ((SecuritySettings) getParentFragment());
+ final boolean compliant = getArguments().getBoolean(EXTRA_COMPLIANT);
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.lock_settings_profile_unification_dialog_title)
+ .setMessage(compliant ? R.string.lock_settings_profile_unification_dialog_body
+ : R.string.lock_settings_profile_unification_dialog_uncompliant_body)
+ .setPositiveButton(compliant ? R.string.okay
+ : R.string.lock_settings_profile_unification_dialog_uncompliant_confirm,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int whichButton) {
+ if (compliant) {
+ parentFragment.launchConfirmDeviceLockForUnification();
+ } else {
+ parentFragment.unifyUncompliantLocks();
+ }
+ }
+ }
+ )
+ .setNegativeButton(R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int whichButton) {
+ parentFragment.updateUnificationPreference();
+ dismiss();
+ }
+ }
+ )
+ .create();
+ }
+ }
+
}
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index 49d72b4..e871c82 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -242,9 +242,18 @@
protected void setHeaderView(int resource) {
mHeader = new LayoutPreference(getPrefContext(), resource);
- mHeader.setOrder(ORDER_FIRST);
+ addPreferenceToTop(mHeader);
+ }
+
+ protected void setHeaderView(View view) {
+ mHeader = new LayoutPreference(getPrefContext(), view);
+ addPreferenceToTop(mHeader);
+ }
+
+ private void addPreferenceToTop(LayoutPreference preference) {
+ preference.setOrder(ORDER_FIRST);
if (getPreferenceScreen() != null) {
- getPreferenceScreen().addPreference(mHeader);
+ getPreferenceScreen().addPreference(preference);
}
}
diff --git a/src/com/android/settings/SetupChooseLockPattern.java b/src/com/android/settings/SetupChooseLockPattern.java
index 69e60be..3a548bc 100644
--- a/src/com/android/settings/SetupChooseLockPattern.java
+++ b/src/com/android/settings/SetupChooseLockPattern.java
@@ -136,6 +136,20 @@
super.updateStage(stage);
// Only enable the button for retry
mRetryButton.setEnabled(stage == Stage.FirstChoiceValid);
+
+ switch (stage) {
+ case Introduction:
+ case HelpScreen:
+ case ChoiceTooShort:
+ case FirstChoiceValid:
+ mRetryButton.setVisibility(View.VISIBLE);
+ break;
+ case NeedToConfirm:
+ case ConfirmWrong:
+ case ChoiceConfirmed:
+ mRetryButton.setVisibility(View.INVISIBLE);
+ break;
+ }
}
@Override
diff --git a/src/com/android/settings/SetupEncryptionInterstitial.java b/src/com/android/settings/SetupEncryptionInterstitial.java
index 8d061ec..dfb32a6 100644
--- a/src/com/android/settings/SetupEncryptionInterstitial.java
+++ b/src/com/android/settings/SetupEncryptionInterstitial.java
@@ -21,11 +21,15 @@
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
+import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
import com.android.setupwizardlib.SetupWizardLayout;
+import com.android.setupwizardlib.SetupWizardPreferenceLayout;
import com.android.setupwizardlib.view.NavigationBar;
/**
@@ -70,26 +74,44 @@
implements NavigationBar.NavigationBarListener {
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- return inflater.inflate(R.layout.setup_encryption_interstitial, container, false);
- }
-
- @Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- final SetupWizardLayout layout =
- (SetupWizardLayout) view.findViewById(R.id.setup_wizard_layout);
+ final SetupWizardPreferenceLayout layout = (SetupWizardPreferenceLayout) view;
+ layout.setDividerInset(getContext().getResources().getDimensionPixelSize(
+ R.dimen.suw_items_text_divider_inset));
+ layout.setIllustration(R.drawable.setup_illustration_lock_screen,
+ R.drawable.setup_illustration_horizontal_tile);
final NavigationBar navigationBar = layout.getNavigationBar();
navigationBar.setNavigationBarListener(this);
+ Button nextButton = navigationBar.getNextButton();
+ nextButton.setText(null);
+ nextButton.setEnabled(false);
+ layout.setHeaderText(R.string.encryption_interstitial_header);
Activity activity = getActivity();
if (activity != null) {
- activity.setTitle(R.string.encryption_interstitial_header);
SetupWizardUtils.setImmersiveMode(activity);
}
+
+ // Use the dividers in SetupWizardRecyclerLayout. Suppress the dividers in
+ // PreferenceFragment.
+ setDivider(null);
+ }
+
+ @Override
+ protected TextView createHeaderView() {
+ TextView message = (TextView) LayoutInflater.from(getActivity()).inflate(
+ R.layout.setup_encryption_interstitial_header, null, false);
+ return message;
+ }
+
+ @Override
+ public RecyclerView onCreateRecyclerView(LayoutInflater inflater, ViewGroup parent,
+ Bundle savedInstanceState) {
+ SetupWizardPreferenceLayout layout = (SetupWizardPreferenceLayout) parent;
+ return layout.onCreateRecyclerView(inflater, parent, savedInstanceState);
}
@Override
@@ -102,7 +124,7 @@
@Override
public void onNavigateNext() {
- startLockIntent();
+ // next is handled via the onPreferenceTreeClick method in EncryptionInterstitial
}
}
}
diff --git a/src/com/android/settings/datausage/BillingCyclePreference.java b/src/com/android/settings/datausage/BillingCyclePreference.java
index 84eaabb..44312b7 100644
--- a/src/com/android/settings/datausage/BillingCyclePreference.java
+++ b/src/com/android/settings/datausage/BillingCyclePreference.java
@@ -14,10 +14,8 @@
package com.android.settings.datausage;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.net.NetworkPolicy;
import android.net.NetworkTemplate;
import android.os.Bundle;
@@ -26,6 +24,7 @@
import android.util.AttributeSet;
import com.android.settings.R;
import com.android.settings.Utils;
+import com.android.settings.datausage.CellDataPreference.DataStateListener;
public class BillingCyclePreference extends Preference implements TemplatePreference {
@@ -41,13 +40,12 @@
@Override
public void onAttached() {
super.onAttached();
- getContext().registerReceiver(mReceiver, new IntentFilter(
- CellDataPreference.ACTION_DATA_ENABLED_CHANGED));
+ mListener.setListener(true, mSubId, getContext());
}
@Override
public void onDetached() {
- getContext().unregisterReceiver(mReceiver);
+ mListener.setListener(false, mSubId, getContext());
super.onDetached();
}
@@ -81,9 +79,9 @@
args, null, 0, getTitle(), false);
}
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ private final DataStateListener mListener = new DataStateListener() {
@Override
- public void onReceive(Context context, Intent intent) {
+ public void onChange(boolean selfChange) {
updateEnabled();
}
};
diff --git a/src/com/android/settings/datausage/CellDataPreference.java b/src/com/android/settings/datausage/CellDataPreference.java
index d64bef4..5e651e4 100644
--- a/src/com/android/settings/datausage/CellDataPreference.java
+++ b/src/com/android/settings/datausage/CellDataPreference.java
@@ -15,14 +15,16 @@
package com.android.settings.datausage;
import android.app.AlertDialog;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
+import android.database.ContentObserver;
import android.net.NetworkTemplate;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
+import android.provider.Settings.Global;
import android.support.v7.preference.PreferenceViewHolder;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -31,7 +33,6 @@
import android.util.Log;
import android.view.View;
import android.widget.Checkable;
-
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.CustomDialogPreference;
@@ -42,10 +43,6 @@
public class CellDataPreference extends CustomDialogPreference implements TemplatePreference {
- // TODO: Get Telephony to broadcast when this changes, and remove this.
- static final String ACTION_DATA_ENABLED_CHANGED =
- "com.android.settings.action.DATA_ENABLED_CHANGED";
-
private static final String TAG = "CellDataPreference";
public int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -84,12 +81,12 @@
@Override
public void onAttached() {
super.onAttached();
- getContext().registerReceiver(mReceiver, new IntentFilter(ACTION_DATA_ENABLED_CHANGED));
+ mListener.setListener(true, mSubId, getContext());
}
@Override
public void onDetached() {
- getContext().unregisterReceiver(mReceiver);
+ mListener.setListener(false, mSubId, getContext());
super.onDetached();
}
@@ -98,6 +95,7 @@
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
throw new IllegalArgumentException("CellDataPreference needs a SubscriptionInfo");
}
+ mSubscriptionManager = SubscriptionManager.from(getContext());
mTelephonyManager = TelephonyManager.from(getContext());
if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
mSubId = subId;
@@ -114,6 +112,22 @@
protected void performClick(View view) {
MetricsLogger.action(getContext(), MetricsEvent.ACTION_CELL_DATA_TOGGLE, !mChecked);
if (mChecked) {
+ final SubscriptionInfo currentSir = mSubscriptionManager.getActiveSubscriptionInfo(
+ mSubId);
+ final SubscriptionInfo nextSir = mSubscriptionManager.getDefaultDataSubscriptionInfo();
+
+ // If the device is single SIM or is enabling data on the active data SIM then forgo
+ // the pop-up.
+ if (!Utils.showSimCardTile(getContext()) ||
+ (nextSir != null && currentSir != null &&
+ currentSir.getSubscriptionId() == nextSir.getSubscriptionId())) {
+ setMobileDataEnabled(true);
+ if (nextSir != null && currentSir != null &&
+ currentSir.getSubscriptionId() == nextSir.getSubscriptionId()) {
+ disableDataForOtherSubscriptions(mSubId);
+ }
+ return;
+ }
// disabling data; show confirmation dialog which eventually
// calls setMobileDataEnabled() once user confirms.
mMultiSimDialog = false;
@@ -130,10 +144,10 @@
}
private void setMobileDataEnabled(boolean enabled) {
- if (DataUsageSummary.LOGD) Log.d(TAG, "setMobileDataEnabled()");
+ if (DataUsageSummary.LOGD) Log.d(TAG, "setMobileDataEnabled(" + enabled + ","
+ + mSubId + ")");
mTelephonyManager.setDataEnabled(mSubId, enabled);
setChecked(enabled);
- getContext().sendBroadcast(new Intent(ACTION_DATA_ENABLED_CHANGED));
}
private void setChecked(boolean checked) {
@@ -170,24 +184,9 @@
private void showMultiSimDialog(AlertDialog.Builder builder,
DialogInterface.OnClickListener listener) {
- mSubscriptionManager = SubscriptionManager.from(getContext());
final SubscriptionInfo currentSir = mSubscriptionManager.getActiveSubscriptionInfo(mSubId);
-
final SubscriptionInfo nextSir = mSubscriptionManager.getDefaultDataSubscriptionInfo();
- // If the device is single SIM or is enabling data on the active data SIM then forgo
- // the pop-up.
- if (!Utils.showSimCardTile(getContext()) ||
- (nextSir != null && currentSir != null &&
- currentSir.getSubscriptionId() == nextSir.getSubscriptionId())) {
- setMobileDataEnabled(true);
- if (nextSir != null && currentSir != null &&
- currentSir.getSubscriptionId() == nextSir.getSubscriptionId()) {
- disableDataForOtherSubscriptions(mSubId);
- }
- return;
- }
-
final String previousName = (nextSir == null)
? getContext().getResources().getString(R.string.sim_selection_required_pref)
: nextSir.getDisplayName().toString();
@@ -197,17 +196,8 @@
String.valueOf(currentSir != null ? currentSir.getDisplayName() : null),
previousName));
- builder.setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- mSubscriptionManager.setDefaultDataSubId(mSubId);
- setMobileDataEnabled(true);
- disableDataForOtherSubscriptions(mSubId);
- }
- });
+ builder.setPositiveButton(R.string.okay, listener);
builder.setNegativeButton(R.string.cancel, null);
-
- builder.create().show();
}
private void disableDataForOtherSubscriptions(int subId) {
@@ -219,7 +209,6 @@
}
}
}
- getContext().sendBroadcast(new Intent(ACTION_DATA_ENABLED_CHANGED));
}
@Override
@@ -228,19 +217,40 @@
return;
}
if (mMultiSimDialog) {
+ mSubscriptionManager.setDefaultDataSubId(mSubId);
+ setMobileDataEnabled(true);
+ disableDataForOtherSubscriptions(mSubId);
} else {
// TODO: extend to modify policy enabled flag.
setMobileDataEnabled(false);
}
}
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ private final DataStateListener mListener = new DataStateListener() {
@Override
- public void onReceive(Context context, Intent intent) {
+ public void onChange(boolean selfChange) {
updateChecked();
}
};
+ public abstract static class DataStateListener extends ContentObserver {
+ public DataStateListener() {
+ super(new Handler(Looper.getMainLooper()));
+ }
+
+ public void setListener(boolean listening, int subId, Context context) {
+ if (listening) {
+ Uri uri = Global.getUriFor(Global.MOBILE_DATA);
+ if (TelephonyManager.getDefault().getSimCount() != 1) {
+ uri = Global.getUriFor(Global.MOBILE_DATA + subId);
+ }
+ context.getContentResolver().registerContentObserver(uri, false, this);
+ } else {
+ context.getContentResolver().unregisterContentObserver(this);
+ }
+ }
+ }
+
public static class CellDataState extends BaseSavedState {
public int mSubId;
public boolean mChecked;
diff --git a/src/com/android/settings/display/DisplayDensityUtils.java b/src/com/android/settings/display/DisplayDensityUtils.java
index 891b7fb..6810511 100644
--- a/src/com/android/settings/display/DisplayDensityUtils.java
+++ b/src/com/android/settings/display/DisplayDensityUtils.java
@@ -46,14 +46,14 @@
/** Maximum density scale. The actual scale used depends on the device. */
private static final float MAX_SCALE = 1.50f;
- /** Summary used for "normal" scale. */
- private static final int SUMMARY_NORMAL = R.string.screen_zoom_summary_normal;
+ /** Summary used for "default" scale. */
+ private static final int SUMMARY_DEFAULT = R.string.screen_zoom_summary_default;
/** Summary used for "custom" scale. */
private static final int SUMMARY_CUSTOM = R.string.screen_zoom_summary_custom;
/**
- * Summaries for scales smaller than "normal" in order of smallest to
+ * Summaries for scales smaller than "default" in order of smallest to
* largest.
*/
private static final int[] SUMMARIES_SMALLER = new int[] {
@@ -61,7 +61,7 @@
};
/**
- * Summaries for scales larger than "normal" in order of smallest to
+ * Summaries for scales larger than "default" in order of smallest to
* largest.
*/
private static final int[] SUMMARIES_LARGER = new int[] {
@@ -80,16 +80,16 @@
private final String[] mEntries;
private final int[] mValues;
- private final int mNormalDensity;
+ private final int mDefaultDensity;
private final int mCurrentIndex;
public DisplayDensityUtils(Context context) {
- final int normalDensity = DisplayDensityUtils.getNormalDisplayDensity(
+ final int defaultDensity = DisplayDensityUtils.getDefaultDisplayDensity(
Display.DEFAULT_DISPLAY);
- if (normalDensity <= 0) {
+ if (defaultDensity <= 0) {
mEntries = null;
mValues = null;
- mNormalDensity = 0;
+ mDefaultDensity = 0;
mCurrentIndex = -1;
return;
}
@@ -102,7 +102,7 @@
// Compute number of "larger" and "smaller" scales for this display.
final int minDimensionPx = Math.min(metrics.widthPixels, metrics.heightPixels);
final int maxDensity = DisplayMetrics.DENSITY_MEDIUM * minDimensionPx / MIN_DIMENSION_DP;
- final float maxScale = Math.min(MAX_SCALE, maxDensity / (float) normalDensity);
+ final float maxScale = Math.min(MAX_SCALE, maxDensity / (float) defaultDensity);
final float minScale = MIN_SCALE;
final int numLarger = (int) MathUtils.constrain((maxScale - 1) / MIN_SCALE_INTERVAL,
0, SUMMARIES_LARGER.length);
@@ -117,7 +117,7 @@
final float interval = (1 - minScale) / numSmaller;
for (int i = numSmaller - 1; i >= 0; i--) {
// Round down to a multiple of 2 by truncating the low bit.
- final int density = ((int) (normalDensity * (1 - (i + 1) * interval))) & ~1;
+ final int density = ((int) (defaultDensity * (1 - (i + 1) * interval))) & ~1;
if (currentDensity == density) {
currentDensityIndex = curIndex;
}
@@ -127,18 +127,18 @@
}
}
- if (currentDensity == normalDensity) {
+ if (currentDensity == defaultDensity) {
currentDensityIndex = curIndex;
}
- values[curIndex] = normalDensity;
- entries[curIndex] = res.getString(SUMMARY_NORMAL);
+ values[curIndex] = defaultDensity;
+ entries[curIndex] = res.getString(SUMMARY_DEFAULT);
curIndex++;
if (numLarger > 0) {
final float interval = (maxScale - 1) / numLarger;
for (int i = 0; i < numLarger; i++) {
// Round down to a multiple of 2 by truncating the low bit.
- final int density = ((int) (normalDensity * (1 + (i + 1) * interval))) & ~1;
+ final int density = ((int) (defaultDensity * (1 + (i + 1) * interval))) & ~1;
if (currentDensity == density) {
currentDensityIndex = curIndex;
}
@@ -163,7 +163,7 @@
displayIndex = curIndex;
}
- mNormalDensity = normalDensity;
+ mDefaultDensity = defaultDensity;
mCurrentIndex = displayIndex;
mEntries = entries;
mValues = values;
@@ -181,18 +181,18 @@
return mCurrentIndex;
}
- public int getNormalDensity() {
- return mNormalDensity;
+ public int getDefaultDensity() {
+ return mDefaultDensity;
}
/**
- * Returns the normal (default) density for the specified display.
+ * Returns the default density for the specified display.
*
* @param displayId the identifier of the display
- * @return the normal density of the specified display, or {@code -1} if
+ * @return the default density of the specified display, or {@code -1} if
* the display does not exist or the density could not be obtained
*/
- private static int getNormalDisplayDensity(int displayId) {
+ private static int getDefaultDisplayDensity(int displayId) {
try {
final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
return wm.getInitialDisplayDensity(displayId);
diff --git a/src/com/android/settings/display/ScreenZoomSettings.java b/src/com/android/settings/display/ScreenZoomSettings.java
index d87f230..f6049c7 100644
--- a/src/com/android/settings/display/ScreenZoomSettings.java
+++ b/src/com/android/settings/display/ScreenZoomSettings.java
@@ -38,7 +38,7 @@
*/
public class ScreenZoomSettings extends PreviewSeekBarPreferenceFragment implements Indexable {
- private int mNormalDensity;
+ private int mDefaultDensity;
private int[] mValues;
@Override
@@ -56,19 +56,19 @@
final int initialIndex = density.getCurrentIndex();
if (initialIndex < 0) {
- // Failed to obtain normal density, which means we failed to
+ // Failed to obtain default density, which means we failed to
// connect to the window manager service. Just use the current
// density and don't let the user change anything.
final int densityDpi = getResources().getDisplayMetrics().densityDpi;
mValues = new int[] { densityDpi };
- mEntries = new String[] { getString(R.string.screen_zoom_summary_normal) };
+ mEntries = new String[] { getString(R.string.screen_zoom_summary_default) };
mInitialIndex = 0;
- mNormalDensity = densityDpi;
+ mDefaultDensity = densityDpi;
} else {
mValues = density.getValues();
mEntries = density.getEntries();
mInitialIndex = initialIndex;
- mNormalDensity = density.getNormalDensity();
+ mDefaultDensity = density.getDefaultDensity();
}
}
@@ -86,7 +86,7 @@
@Override
protected void commit() {
final int densityDpi = mValues[mCurrentIndex];
- if (densityDpi == mNormalDensity) {
+ if (densityDpi == mDefaultDensity) {
DisplayDensityUtils.clearForcedDisplayDensity(Display.DEFAULT_DISPLAY);
} else {
DisplayDensityUtils.setForcedDisplayDensity(Display.DEFAULT_DISPLAY, densityDpi);
diff --git a/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java
index bedeb30..2fe255e 100644
--- a/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/fingerprint/FingerprintEnrollIntroduction.java
@@ -66,9 +66,9 @@
(SetupWizardItemsLayout) findViewById(R.id.setup_wizard_layout);
layout.getListView().setOnItemClickListener(this);
final ItemAdapter adapter = (ItemAdapter) layout.getAdapter();
- Item item = (Item) adapter.findItemById(R.id.fingerprint_introduction_message_warning);
+ Item item = (Item) adapter.findItemById(R.id.fingerprint_introduction_message);
item.setTitle(LearnMoreSpan.linkify(
- getText(R.string.security_settings_fingerprint_enroll_introduction_message_warning),
+ getText(R.string.security_settings_fingerprint_enroll_introduction_message),
getString(R.string.help_url_fingerprint)));
updatePasswordQuality();
}
diff --git a/src/com/android/settings/notification/NotificationStation.java b/src/com/android/settings/notification/NotificationStation.java
index 44f0ffc..7c79e8b 100644
--- a/src/com/android/settings/notification/NotificationStation.java
+++ b/src/com/android/settings/notification/NotificationStation.java
@@ -16,28 +16,31 @@
package com.android.settings.notification;
-import android.app.Activity;
-import android.app.ActivityManager;
+import android.app.*;
import android.app.INotificationManager;
-import android.app.Notification;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.UserHandle;
+import android.os.*;
import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;
import android.support.v7.widget.RecyclerView;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
+import android.text.style.StyleSpan;
import android.util.Log;
import android.view.View;
import android.widget.DateTimeView;
@@ -45,19 +48,20 @@
import android.widget.TextView;
import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.settings.CopyablePreference;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
+import java.lang.StringBuilder;
+import java.util.*;
public class NotificationStation extends SettingsPreferenceFragment {
private static final String TAG = NotificationStation.class.getSimpleName();
private static final boolean DEBUG = false;
+ private static final boolean DUMP_EXTRAS = true;
+ private static final boolean DUMP_PARCEL = true;
private static class HistoricalNotificationInfo {
public String pkg;
@@ -69,10 +73,12 @@
public int user;
public long timestamp;
public boolean active;
+ public CharSequence extra;
}
private PackageManager mPm;
private INotificationManager mNoMan;
+ private RankingMap mRanking;
private Runnable mRefreshListRunnable = new Runnable() {
@Override
@@ -83,19 +89,26 @@
private NotificationListenerService mListener = new NotificationListenerService() {
@Override
- public void onNotificationPosted(StatusBarNotification notification) {
- logd("onNotificationPosted: %s", notification);
+ public void onNotificationPosted(StatusBarNotification sbn, RankingMap ranking) {
+ logd("onNotificationPosted: %s", sbn.getNotification());
final Handler h = getListView().getHandler();
+ mRanking = ranking;
h.removeCallbacks(mRefreshListRunnable);
h.postDelayed(mRefreshListRunnable, 100);
}
@Override
- public void onNotificationRemoved(StatusBarNotification notification) {
+ public void onNotificationRemoved(StatusBarNotification notification, RankingMap ranking) {
final Handler h = getListView().getHandler();
+ mRanking = ranking;
h.removeCallbacks(mRefreshListRunnable);
h.postDelayed(mRefreshListRunnable, 100);
}
+
+ @Override
+ public void onNotificationRankingUpdate(RankingMap ranking) {
+ mRanking = ranking;
+ }
};
private Context mContext;
@@ -179,6 +192,40 @@
}
}
+ private static CharSequence bold(CharSequence cs) {
+ if (cs.length() == 0) return cs;
+ SpannableString ss = new SpannableString(cs);
+ ss.setSpan(new StyleSpan(Typeface.BOLD), 0, cs.length(), 0);
+ return ss;
+ }
+
+ private static String getTitleString(Notification n) {
+ String title = null;
+ if (n.extras != null) {
+ title = n.extras.getString(Notification.EXTRA_TITLE);
+ if (TextUtils.isEmpty(title)) {
+ title = n.extras.getString(Notification.EXTRA_TEXT);
+ }
+ }
+ if (TextUtils.isEmpty(title) && !TextUtils.isEmpty(n.tickerText)) {
+ title = n.tickerText.toString();
+ }
+ return title;
+ }
+
+ private static String formatPendingIntent(PendingIntent pi) {
+ final StringBuilder sb = new StringBuilder();
+ final IntentSender is = pi.getIntentSender();
+ sb.append("Intent(pkg=").append(is.getCreatorPackage());
+ try {
+ final boolean isActivity =
+ ActivityManagerNative.getDefault().isIntentSenderAnActivity(is.getTarget());
+ if (isActivity) sb.append(" (activity)");
+ } catch (RemoteException ex) {}
+ sb.append(")");
+ return sb.toString();
+ }
+
private List<HistoricalNotificationInfo> loadNotifications() {
final int currentUserId = ActivityManager.getCurrentUser();
try {
@@ -190,40 +237,189 @@
List<HistoricalNotificationInfo> list
= new ArrayList<HistoricalNotificationInfo>(active.length + dismissed.length);
+ final Ranking rank = new Ranking();
+
for (StatusBarNotification[] resultset
: new StatusBarNotification[][] { active, dismissed }) {
for (StatusBarNotification sbn : resultset) {
+ if (sbn.getUserId() != UserHandle.USER_ALL & sbn.getUserId() != currentUserId) {
+ continue;
+ }
+
+ final Notification n = sbn.getNotification();
final HistoricalNotificationInfo info = new HistoricalNotificationInfo();
info.pkg = sbn.getPackageName();
info.user = sbn.getUserId();
- info.icon = loadIconDrawable(info.pkg, info.user, sbn.getNotification().icon);
+ info.icon = loadIconDrawable(info.pkg, info.user, n.icon);
info.pkgicon = loadPackageIconDrawable(info.pkg, info.user);
info.pkgname = loadPackageName(info.pkg);
- if (sbn.getNotification().extras != null) {
- info.title = sbn.getNotification().extras.getString(
- Notification.EXTRA_TITLE);
- if (info.title == null || "".equals(info.title)) {
- info.title = sbn.getNotification().extras.getString(
- Notification.EXTRA_TEXT);
- }
- }
- if (info.title == null || "".equals(info.title)) {
- info.title = sbn.getNotification().tickerText;
- }
- // still nothing? come on, give us something!
- if (info.title == null || "".equals(info.title)) {
- info.title = info.pkgname;
+ info.title = getTitleString(n);
+ if (TextUtils.isEmpty(info.title)) {
+ info.title = getString(R.string.notification_log_no_title);
}
info.timestamp = sbn.getPostTime();
- info.priority = sbn.getNotification().priority;
- logd(" [%d] %s: %s", info.timestamp, info.pkg, info.title);
+ info.priority = n.priority;
info.active = (resultset == active);
- if (info.user == UserHandle.USER_ALL
- || info.user == currentUserId) {
- list.add(info);
+ final SpannableStringBuilder sb = new SpannableStringBuilder();
+ final String delim = getString(R.string.notification_log_details_delimiter);
+ sb.append(bold(getString(R.string.notification_log_details_package)))
+ .append(delim)
+ .append(info.pkg)
+ .append("\n")
+ .append(bold(getString(R.string.notification_log_details_key)))
+ .append(delim)
+ .append(sbn.getKey());
+ sb.append("\n")
+ .append(bold(getString(R.string.notification_log_details_icon)))
+ .append(delim)
+ .append(n.getSmallIcon().toString());
+ if (!TextUtils.isEmpty(n.getGroup())) {
+ sb.append("\n")
+ .append(bold(getString(R.string.notification_log_details_group)))
+ .append(delim)
+ .append(n.getGroup());
+ if (n.isGroupSummary()) {
+ sb.append(bold(
+ getString(R.string.notification_log_details_group_summary)));
+ }
}
+ sb.append("\n")
+ .append(bold(getString(R.string.notification_log_details_sound)))
+ .append(delim);
+ if (0 != (n.defaults & Notification.DEFAULT_SOUND)) {
+ sb.append(getString(R.string.notification_log_details_default));
+ } else if (n.sound != null) {
+ sb.append(n.sound.toString());
+ } else {
+ sb.append(getString(R.string.notification_log_details_none));
+ }
+ sb.append("\n")
+ .append(bold(getString(R.string.notification_log_details_vibrate)))
+ .append(delim);
+ if (0 != (n.defaults & Notification.DEFAULT_VIBRATE)) {
+ sb.append(getString(R.string.notification_log_details_default));
+ } else if (n.vibrate != null) {
+ for (int vi=0;vi<n.vibrate.length;vi++) {
+ if (vi > 0) sb.append(',');
+ sb.append(String.valueOf(n.vibrate[vi]));
+ }
+ } else {
+ sb.append(getString(R.string.notification_log_details_none));
+ }
+ sb.append("\n")
+ .append(bold(getString(R.string.notification_log_details_visibility)))
+ .append(delim)
+ .append(Notification.visibilityToString(n.visibility));
+ if (n.publicVersion != null) {
+ sb.append("\n")
+ .append(bold(getString(
+ R.string.notification_log_details_public_version)))
+ .append(delim)
+ .append(getTitleString(n.publicVersion));
+ }
+ sb.append("\n")
+ .append(bold(getString(R.string.notification_log_details_priority)))
+ .append(delim)
+ .append(Notification.priorityToString(n.priority));
+ if (mRanking != null && mRanking.getRanking(sbn.getKey(), rank)) {
+ sb.append("\n")
+ .append(bold(getString(
+ R.string.notification_log_details_importance)))
+ .append(delim)
+ .append(Ranking.importanceToString(rank.getImportance()));
+ if (rank.getImportanceExplanation() != null) {
+ sb.append("\n")
+ .append(bold(getString(
+ R.string.notification_log_details_explanation)))
+ .append(delim)
+ .append(rank.getImportanceExplanation());
+ }
+ }
+ if (n.contentIntent != null) {
+ sb.append("\n")
+ .append(bold(getString(
+ R.string.notification_log_details_content_intent)))
+ .append(delim)
+ .append(formatPendingIntent(n.contentIntent));
+ }
+ if (n.deleteIntent != null) {
+ sb.append("\n")
+ .append(bold(getString(
+ R.string.notification_log_details_delete_intent)))
+ .append(delim)
+ .append(formatPendingIntent(n.deleteIntent));
+ }
+ if (n.fullScreenIntent != null) {
+ sb.append("\n")
+ .append(bold(getString(
+ R.string.notification_log_details_full_screen_intent)))
+ .append(delim)
+ .append(formatPendingIntent(n.fullScreenIntent));
+ }
+ if (n.actions != null && n.actions.length > 0) {
+ sb.append("\n")
+ .append(bold(getString(R.string.notification_log_details_actions)));
+ for (int ai=0; ai<n.actions.length; ai++) {
+ final Notification.Action action = n.actions[ai];
+ sb.append("\n ").append(String.valueOf(ai)).append(' ')
+ .append(bold(getString(
+ R.string.notification_log_details_title)))
+ .append(delim)
+ .append(action.title)
+ .append("\n ")
+ .append(bold(getString(
+ R.string.notification_log_details_content_intent)))
+ .append(delim)
+ .append(formatPendingIntent(action.actionIntent));
+ if (action.getRemoteInputs() != null) {
+ sb.append(' ')
+ .append(bold(getString(
+ R.string.notification_log_details_remoteinput)))
+ .append(delim)
+ .append(String.valueOf(action.getRemoteInputs().length));
+ }
+ }
+ }
+ if (n.contentView != null) {
+ sb.append("\n")
+ .append(bold(getString(
+ R.string.notification_log_details_content_view)))
+ .append(delim)
+ .append(n.contentView.toString());
+ }
+
+ if (DUMP_EXTRAS) {
+ if (n.extras != null && n.extras.size() > 0) {
+ sb.append("\n")
+ .append(bold(getString(
+ R.string.notification_log_details_extras)));
+ for (String extraKey : n.extras.keySet()) {
+ String val = String.valueOf(n.extras.get(extraKey));
+ if (val.length() > 100) val = val.substring(0, 100) + "...";
+ sb.append("\n ").append(extraKey).append(delim).append(val);
+ }
+ }
+ }
+ if (DUMP_PARCEL) {
+ final Parcel p = Parcel.obtain();
+ n.writeToParcel(p, 0);
+ sb.append("\n")
+ .append(bold(getString(R.string.notification_log_details_parcel)))
+ .append(delim)
+ .append(String.valueOf(p.dataPosition()))
+ .append(' ')
+ .append(bold(getString(R.string.notification_log_details_ashmem)))
+ .append(delim)
+ .append(String.valueOf(p.getBlobAshmemSize()))
+ .append("\n");
+ }
+
+ info.extra = sb;
+
+ logd(" [%d] %s: %s", info.timestamp, info.pkg, info.title);
+ list.add(info);
}
}
@@ -293,7 +489,7 @@
return null;
}
- private static class HistoricalNotificationPreference extends Preference {
+ private static class HistoricalNotificationPreference extends CopyablePreference {
private final HistoricalNotificationInfo mInfo;
public HistoricalNotificationPreference(Context context, HistoricalNotificationInfo info) {
@@ -304,27 +500,49 @@
@Override
public void onBindViewHolder(PreferenceViewHolder row) {
+ super.onBindViewHolder(row);
+
if (mInfo.icon != null) {
- ((ImageView) row.findViewById(android.R.id.icon)).setImageDrawable(mInfo.icon);
+ ((ImageView) row.findViewById(R.id.icon)).setImageDrawable(mInfo.icon);
}
if (mInfo.pkgicon != null) {
((ImageView) row.findViewById(R.id.pkgicon)).setImageDrawable(mInfo.pkgicon);
}
((DateTimeView) row.findViewById(R.id.timestamp)).setTime(mInfo.timestamp);
- ((TextView) row.findViewById(android.R.id.title)).setText(mInfo.title);
+ ((TextView) row.findViewById(R.id.title)).setText(mInfo.title);
((TextView) row.findViewById(R.id.pkgname)).setText(mInfo.pkgname);
- row.findViewById(R.id.extra).setVisibility(View.GONE);
+ final TextView extra = (TextView) row.findViewById(R.id.extra);
+ extra.setText(mInfo.extra);
+ extra.setVisibility(View.GONE);
+
+ row.itemView.setOnClickListener(
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ extra.setVisibility(extra.getVisibility() == View.VISIBLE
+ ? View.GONE : View.VISIBLE);
+ }
+ });
+
row.itemView.setAlpha(mInfo.active ? 1.0f : 0.5f);
}
@Override
+ public CharSequence getCopyableText() {
+ return new SpannableStringBuilder(mInfo.title)
+ .append(" [").append(new Date(mInfo.timestamp).toString())
+ .append("]\n").append(mInfo.pkgname)
+ .append("\n").append(mInfo.extra);
+ }
+
+ @Override
public void performClick() {
- Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
- Uri.fromParts("package", mInfo.pkg, null));
- intent.setComponent(intent.resolveActivity(getContext().getPackageManager()));
- getContext().startActivity(intent);
+// Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+// Uri.fromParts("package", mInfo.pkg, null));
+// intent.setComponent(intent.resolveActivity(getContext().getPackageManager()));
+// getContext().startActivity(intent);
}
}
}